dd-trace 2.0.0-appsec-alpha.1 → 2.0.0-appsec-beta.1

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 (58) hide show
  1. package/LICENSE-3rdparty.csv +1 -1
  2. package/index.d.ts +0 -6
  3. package/package.json +12 -10
  4. package/packages/datadog-core/index.js +7 -0
  5. package/packages/datadog-core/src/storage/async_hooks.js +49 -0
  6. package/packages/datadog-core/src/storage/async_resource.js +76 -0
  7. package/packages/datadog-core/src/storage/index.js +14 -0
  8. package/packages/datadog-plugin-cucumber/src/index.js +8 -13
  9. package/packages/datadog-plugin-cypress/src/plugin.js +5 -3
  10. package/packages/datadog-plugin-graphql/src/index.js +16 -10
  11. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  12. package/packages/datadog-plugin-http/src/server.js +1 -1
  13. package/packages/datadog-plugin-jest/src/jest-environment.js +8 -3
  14. package/packages/datadog-plugin-jest/src/jest-jasmine2.js +15 -5
  15. package/packages/datadog-plugin-mocha/src/index.js +15 -6
  16. package/packages/dd-trace/src/appsec/addresses.js +4 -2
  17. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +25 -41
  18. package/packages/dd-trace/src/appsec/index.js +59 -26
  19. package/packages/dd-trace/src/appsec/recommended.json +1 -1
  20. package/packages/dd-trace/src/appsec/reporter.js +142 -113
  21. package/packages/dd-trace/src/appsec/rule_manager.js +3 -1
  22. package/packages/dd-trace/src/config.js +1 -5
  23. package/packages/dd-trace/src/encode/0.4.js +84 -23
  24. package/packages/dd-trace/src/encode/chunk.js +12 -14
  25. package/packages/dd-trace/src/gateway/channels.js +1 -1
  26. package/packages/dd-trace/src/gateway/dc_block.js +12 -7
  27. package/packages/dd-trace/src/gateway/engine/engine.js +12 -9
  28. package/packages/dd-trace/src/gateway/engine/runner.js +8 -7
  29. package/packages/dd-trace/src/id.js +22 -18
  30. package/packages/dd-trace/src/instrumenter.js +2 -2
  31. package/packages/dd-trace/src/loader.js +16 -50
  32. package/packages/dd-trace/src/noop/scope.js +23 -0
  33. package/packages/dd-trace/src/noop/span.js +2 -0
  34. package/packages/dd-trace/src/noop/tracer.js +3 -10
  35. package/packages/dd-trace/src/opentracing/span.js +10 -0
  36. package/packages/dd-trace/src/plugins/util/ci-app-spec.json +1 -0
  37. package/packages/dd-trace/src/plugins/util/ci.js +9 -5
  38. package/packages/dd-trace/src/plugins/util/git.js +11 -25
  39. package/packages/dd-trace/src/plugins/util/redis.js +1 -1
  40. package/packages/dd-trace/src/plugins/util/test.js +26 -1
  41. package/packages/dd-trace/src/plugins/util/user-provided-git.js +57 -0
  42. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  43. package/packages/dd-trace/src/profiling/exporters/agent.js +11 -4
  44. package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -3
  45. package/packages/dd-trace/src/proxy.js +1 -1
  46. package/packages/dd-trace/src/scope.js +212 -18
  47. package/packages/dd-trace/src/span_processor.js +76 -2
  48. package/packages/dd-trace/src/startup-log.js +0 -1
  49. package/packages/dd-trace/src/tracer.js +4 -19
  50. package/NOTICE +0 -4
  51. package/packages/dd-trace/src/gateway/dc.js +0 -4
  52. package/packages/dd-trace/src/scope/async_hooks.js +0 -139
  53. package/packages/dd-trace/src/scope/async_local_storage.js +0 -29
  54. package/packages/dd-trace/src/scope/async_resource.js +0 -82
  55. package/packages/dd-trace/src/scope/base.js +0 -218
  56. package/packages/dd-trace/src/scope/scope_manager.js +0 -5
  57. package/packages/dd-trace/src/scope/sync.js +0 -29
  58. package/packages/dd-trace/src/scope/zone.js +0 -38
@@ -20,6 +20,7 @@ require,multer,MIT,Copyright 2014 Hage Yaapa
20
20
  require,opentracing,MIT,Copyright 2016 Resonance Labs Inc
21
21
  require,path-to-regexp,MIT,Copyright 2014 Blake Embrey
22
22
  require,performance-now,MIT,Copyright 2013 Braveg1rl
23
+ require,retry,MIT,Copyright 2011 Tim Koschützki Felix Geisendörfer
23
24
  require,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
24
25
  require,source-map,BSD-3-Clause,Copyright 2009-2011 Mozilla Foundation and contributors
25
26
  require,source-map-resolve,MIT,Copyright 2014-2020 Simon Lydell 2019 Jinxiang
@@ -53,7 +54,6 @@ dev,msgpack-lite,MIT,Copyright 2015 Yusuke Kawasaki
53
54
  dev,nock,MIT,Copyright 2017 Pedro Teixeira and other contributors
54
55
  dev,nyc,ISC,Copyright 2015 Contributors
55
56
  dev,proxyquire,MIT,Copyright 2013 Thorsten Lorenz
56
- dev,retry,MIT,Copyright 2011 Tim Koschützki Felix Geisendörfer
57
57
  dev,rimraf,ISC,Copyright Isaac Z. Schlueter and Contributors
58
58
  dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
59
59
  dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
package/index.d.ts CHANGED
@@ -285,12 +285,6 @@ export declare interface TracerOptions {
285
285
  */
286
286
  runtimeMetrics?: boolean
287
287
 
288
- /**
289
- * Whether to track the scope of async functions. This is needed for async/await to work with non-native promises (thenables). Only disable this if you are sure only native promises are used with async/await, or if you are using Node >=14.5 since the issue has been fixed in that version.
290
- * @default true
291
- */
292
- trackAsyncScope?: boolean
293
-
294
288
  /**
295
289
  * Custom function for DNS lookups when sending requests to the agent.
296
290
  * @default dns.lookup()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "2.0.0-appsec-alpha.1",
3
+ "version": "2.0.0-appsec-beta.1",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -16,8 +16,10 @@
16
16
  "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
17
17
  "tdd": "node scripts/tdd.js",
18
18
  "test": "SERVICES=* yarn services && mocha --exit --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
19
- "test:core": "mocha --exit --expose-gc --file packages/dd-trace/test/setup/core.js \"packages/dd-trace/test/**/*.spec.js\"",
20
- "test:core:ci": "nyc --include \"packages/dd-trace/src/**/*.js\" -- npm run test:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
19
+ "test:trace:core": "mocha --exit --expose-gc --file packages/dd-trace/test/setup/core.js \"packages/dd-trace/test/**/*.spec.js\"",
20
+ "test:trace:core:ci": "nyc --include \"packages/dd-trace/src/**/*.js\" -- npm run test:trace:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
21
+ "test:core": "mocha --file packages/datadog-core/test/setup.js 'packages/datadog-core/test/**/*.spec.js'",
22
+ "test:core:ci": "nyc --include 'packages/datadog-core/src/**/*.js' -- npm run test:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
21
23
  "test:plugins": "mocha --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\"",
22
24
  "test:plugins:ci": "yarn services && nyc --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
23
25
  "test:plugins:upstream": "node ./packages/dd-trace/test/plugins/suite.js",
@@ -56,15 +58,15 @@
56
58
  "node": ">=12"
57
59
  },
58
60
  "dependencies": {
59
- "@datadog/native-appsec": "^0.3.1",
60
- "@datadog/native-metrics": "^1.0.0",
61
- "@datadog/pprof": "^0.1.3",
61
+ "@datadog/native-appsec": "^0.6.0",
62
+ "@datadog/native-metrics": "^1.0.1",
63
+ "@datadog/pprof": "^0.3.0",
62
64
  "@datadog/sketches-js": "^1.0.4",
63
65
  "@types/node": "^10.12.18",
64
66
  "crypto-randomuuid": "^1.0.0",
65
- "diagnostics_channel": "^1.0.0",
67
+ "diagnostics_channel": "^1.1.0",
66
68
  "form-data": "^3.0.0",
67
- "import-in-the-middle": "^1.1.1",
69
+ "import-in-the-middle": "^1.1.2",
68
70
  "koalas": "^1.0.2",
69
71
  "limiter": "^1.1.4",
70
72
  "lodash.kebabcase": "^4.1.1",
@@ -77,13 +79,14 @@
77
79
  "opentracing": ">=0.12.1",
78
80
  "path-to-regexp": "^0.1.2",
79
81
  "performance-now": "^2.1.0",
82
+ "retry": "^0.10.1",
80
83
  "semver": "^5.5.0",
81
84
  "source-map": "^0.7.3",
82
85
  "source-map-resolve": "^0.6.0"
83
86
  },
84
87
  "devDependencies": {
85
88
  "autocannon": "^4.5.2",
86
- "axios": "^0.21.1",
89
+ "axios": "^0.21.2",
87
90
  "benchmark": "^2.1.4",
88
91
  "body-parser": "^1.18.2",
89
92
  "chai": "^4.2.0",
@@ -112,7 +115,6 @@
112
115
  "nock": "^11.3.3",
113
116
  "nyc": "^15.1.0",
114
117
  "proxyquire": "^1.8.0",
115
- "retry": "^0.10.1",
116
118
  "rimraf": "^3.0.0",
117
119
  "sinon": "^11.1.2",
118
120
  "sinon-chai": "^3.7.0",
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const LocalStorage = require('./src/storage')
4
+
5
+ const storage = new LocalStorage()
6
+
7
+ module.exports = { storage }
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const { createHook, executionAsyncId } = require('async_hooks')
4
+ const AsyncResourceStorage = require('./async_resource')
5
+
6
+ class AsyncHooksStorage extends AsyncResourceStorage {
7
+ constructor () {
8
+ super()
9
+
10
+ this._resources = new Map()
11
+ }
12
+
13
+ disable () {
14
+ super.disable()
15
+
16
+ this._resources.clear()
17
+ }
18
+
19
+ _createHook () {
20
+ return createHook({
21
+ init: this._init.bind(this),
22
+ destroy: this._destroy.bind(this)
23
+ })
24
+ }
25
+
26
+ _init (asyncId, type, triggerAsyncId, resource) {
27
+ super._init.apply(this, arguments)
28
+
29
+ this._resources.set(asyncId, resource)
30
+ }
31
+
32
+ _destroy (asyncId) {
33
+ this._resources.delete(asyncId)
34
+ }
35
+
36
+ _executionAsyncResource () {
37
+ const asyncId = executionAsyncId()
38
+
39
+ let resource = this._resources.get(asyncId)
40
+
41
+ if (!resource) {
42
+ this._resources.set(asyncId, resource = {})
43
+ }
44
+
45
+ return resource
46
+ }
47
+ }
48
+
49
+ module.exports = AsyncHooksStorage
@@ -0,0 +1,76 @@
1
+ 'use strict'
2
+
3
+ const { createHook, executionAsyncResource } = require('async_hooks')
4
+
5
+ class AsyncResourceStorage {
6
+ constructor () {
7
+ this._ddResourceStore = Symbol('ddResourceStore')
8
+ this._enabled = false
9
+ this._hook = this._createHook()
10
+ }
11
+
12
+ disable () {
13
+ if (!this._enabled) return
14
+
15
+ this._hook.disable()
16
+ this._enabled = false
17
+ }
18
+
19
+ getStore () {
20
+ if (!this._enabled) return
21
+
22
+ const resource = this._executionAsyncResource()
23
+
24
+ return resource[this._ddResourceStore]
25
+ }
26
+
27
+ enterWith (store) {
28
+ this._enable()
29
+
30
+ const resource = this._executionAsyncResource()
31
+
32
+ resource[this._ddResourceStore] = store
33
+ }
34
+
35
+ run (store, callback, ...args) {
36
+ this._enable()
37
+
38
+ const resource = this._executionAsyncResource()
39
+ const oldStore = resource[this._ddResourceStore]
40
+
41
+ resource[this._ddResourceStore] = store
42
+
43
+ try {
44
+ return callback(...args)
45
+ } finally {
46
+ resource[this._ddResourceStore] = oldStore
47
+ }
48
+ }
49
+
50
+ _createHook () {
51
+ return createHook({
52
+ init: this._init.bind(this)
53
+ })
54
+ }
55
+
56
+ _enable () {
57
+ if (this._enabled) return
58
+
59
+ this._enabled = true
60
+ this._hook.enable()
61
+ }
62
+
63
+ _init (asyncId, type, triggerAsyncId, resource) {
64
+ const currentResource = this._executionAsyncResource()
65
+
66
+ if (Object.prototype.hasOwnProperty.call(currentResource, this._ddResourceStore)) {
67
+ resource[this._ddResourceStore] = currentResource[this._ddResourceStore]
68
+ }
69
+ }
70
+
71
+ _executionAsyncResource () {
72
+ return executionAsyncResource()
73
+ }
74
+ }
75
+
76
+ module.exports = AsyncResourceStorage
@@ -0,0 +1,14 @@
1
+ 'use strict'
2
+
3
+ // TODO: default to AsyncLocalStorage when it supports triggerAsyncResource
4
+
5
+ const semver = require('semver')
6
+
7
+ // https://github.com/nodejs/node/pull/33801
8
+ const hasJavaScriptAsyncHooks = semver.satisfies(process.versions.node, '>=14.5 || ^12.19.0')
9
+
10
+ if (hasJavaScriptAsyncHooks) {
11
+ module.exports = require('./async_resource')
12
+ } else {
13
+ module.exports = require('./async_hooks')
14
+ }
@@ -1,5 +1,3 @@
1
- const { relative } = require('path')
2
-
3
1
  const { SAMPLING_RULE_DECISION } = require('../../dd-trace/src/constants')
4
2
 
5
3
  const {
@@ -7,11 +5,13 @@ const {
7
5
  TEST_NAME,
8
6
  TEST_SUITE,
9
7
  TEST_STATUS,
8
+ TEST_FRAMEWORK_VERSION,
10
9
  TEST_SKIP_REASON,
11
10
  CI_APP_ORIGIN,
12
11
  ERROR_MESSAGE,
13
12
  getTestEnvironmentMetadata,
14
- finishAllTraceSpans
13
+ finishAllTraceSpans,
14
+ getTestSuitePath
15
15
  } = require('../../dd-trace/src/plugins/util/test')
16
16
 
17
17
  function setStatusFromResult (span, result, tag) {
@@ -42,17 +42,18 @@ function setStatusFromResultLatest (span, result, tag) {
42
42
  }
43
43
  }
44
44
 
45
- function createWrapRun (tracer, testEnvironmentMetadata, getTestSuiteName, setStatus) {
45
+ function createWrapRun (tracer, testEnvironmentMetadata, sourceRoot, setStatus) {
46
46
  return function wrapRun (run) {
47
47
  return function handleRun () {
48
48
  const testName = this.pickle.name
49
- const testSuite = getTestSuiteName(this.pickle.uri)
49
+ const testSuite = getTestSuitePath(this.pickle.uri, sourceRoot)
50
50
 
51
51
  const commonSpanTags = {
52
52
  [TEST_TYPE]: 'test',
53
53
  [TEST_NAME]: testName,
54
54
  [TEST_SUITE]: testSuite,
55
55
  [SAMPLING_RULE_DECISION]: 1,
56
+ [TEST_FRAMEWORK_VERSION]: tracer._version,
56
57
  ...testEnvironmentMetadata
57
58
  }
58
59
 
@@ -105,14 +106,11 @@ module.exports = [
105
106
  patch (PickleRunner, tracer) {
106
107
  const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber')
107
108
  const sourceRoot = process.cwd()
108
- const getTestSuiteName = (pickleUri) => {
109
- return relative(sourceRoot, pickleUri)
110
- }
111
109
  const pl = PickleRunner.default
112
110
  this.wrap(
113
111
  pl.prototype,
114
112
  'run',
115
- createWrapRun(tracer, testEnvironmentMetadata, getTestSuiteName, setStatusFromResult)
113
+ createWrapRun(tracer, testEnvironmentMetadata, sourceRoot, setStatusFromResult)
116
114
  )
117
115
  const getResourceName = (testStep) => {
118
116
  return testStep.isHook ? 'hook' : testStep.pickleStep.text
@@ -132,14 +130,11 @@ module.exports = [
132
130
  patch (TestCaseRunner, tracer) {
133
131
  const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber')
134
132
  const sourceRoot = process.cwd()
135
- const getTestSuiteName = (pickleUri) => {
136
- return relative(sourceRoot, pickleUri)
137
- }
138
133
  const pl = TestCaseRunner.default
139
134
  this.wrap(
140
135
  pl.prototype,
141
136
  'run',
142
- createWrapRun(tracer, testEnvironmentMetadata, getTestSuiteName, setStatusFromResultLatest)
137
+ createWrapRun(tracer, testEnvironmentMetadata, sourceRoot, setStatusFromResultLatest)
143
138
  )
144
139
  const getResourceName = (testStep) => {
145
140
  return testStep.text
@@ -3,6 +3,7 @@ const {
3
3
  TEST_NAME,
4
4
  TEST_SUITE,
5
5
  TEST_STATUS,
6
+ TEST_FRAMEWORK_VERSION,
6
7
  getTestEnvironmentMetadata,
7
8
  CI_APP_ORIGIN,
8
9
  getTestParentSpan
@@ -19,7 +20,7 @@ const CYPRESS_STATUS_TO_TEST_STATUS = {
19
20
  skipped: 'skip'
20
21
  }
21
22
 
22
- function getTestSpanMetadata (tracer, testName, testSuite) {
23
+ function getTestSpanMetadata (tracer, testName, testSuite, cypressConfig) {
23
24
  const childOf = getTestParentSpan(tracer)
24
25
 
25
26
  return {
@@ -29,7 +30,8 @@ function getTestSpanMetadata (tracer, testName, testSuite) {
29
30
  [TEST_NAME]: testName,
30
31
  [TEST_SUITE]: testSuite,
31
32
  [SAMPLING_RULE_DECISION]: 1,
32
- [SAMPLING_PRIORITY]: AUTO_KEEP
33
+ [SAMPLING_PRIORITY]: AUTO_KEEP,
34
+ [TEST_FRAMEWORK_VERSION]: cypressConfig.version
33
35
  }
34
36
  }
35
37
 
@@ -50,7 +52,7 @@ module.exports = (on, config) => {
50
52
  childOf,
51
53
  resource,
52
54
  ...testSpanMetadata
53
- } = getTestSpanMetadata(tracer, testName, testSuite)
55
+ } = getTestSpanMetadata(tracer, testName, testSuite, config)
54
56
 
55
57
  if (!activeSpan) {
56
58
  activeSpan = tracer.startSpan('cypress.test', {
@@ -9,20 +9,17 @@ let tools
9
9
  function createWrapExecute (tracer, config, defaultFieldResolver) {
10
10
  return function wrapExecute (execute) {
11
11
  return function executeWithTrace () {
12
- const args = normalizeArgs(arguments)
12
+ const args = normalizeArgs(arguments, tracer, config, defaultFieldResolver)
13
13
  const schema = args.schema
14
14
  const document = args.document
15
15
  const source = document && document._datadog_source
16
- const fieldResolver = args.fieldResolver || defaultFieldResolver
17
- const contextValue = args.contextValue = args.contextValue || {}
16
+ const contextValue = args.contextValue
18
17
  const operation = getOperation(document, args.operationName)
19
18
 
20
19
  if (contextValue._datadog_graphql) {
21
20
  return execute.apply(this, arguments)
22
21
  }
23
22
 
24
- args.fieldResolver = wrapResolve(fieldResolver, tracer, config)
25
-
26
23
  if (schema) {
27
24
  wrapFields(schema._queryType, tracer, config)
28
25
  wrapFields(schema._mutationType, tracer, config)
@@ -32,7 +29,7 @@ function createWrapExecute (tracer, config, defaultFieldResolver) {
32
29
 
33
30
  contextValue._datadog_graphql = { source, span, fields: {} }
34
31
 
35
- return call(execute, span, this, [args], (err, res) => {
32
+ return call(execute, span, this, arguments, (err, res) => {
36
33
  finishResolvers(contextValue, config)
37
34
 
38
35
  setError(span, err || (res && res.errors && res.errors[0]))
@@ -212,10 +209,19 @@ function getField (contextValue, path) {
212
209
  return contextValue._datadog_graphql.fields[path.join('.')]
213
210
  }
214
211
 
215
- function normalizeArgs (args) {
216
- if (args.length === 1) {
217
- return args[0]
218
- }
212
+ function normalizeArgs (args, tracer, config, defaultFieldResolver) {
213
+ if (args.length !== 1) return normalizePositional(args, tracer, config, defaultFieldResolver)
214
+
215
+ args[0].contextValue = args[0].contextValue || {}
216
+ args[0].fieldResolver = wrapResolve(args[0].fieldResolver || defaultFieldResolver, tracer, config)
217
+
218
+ return args[0]
219
+ }
220
+
221
+ function normalizePositional (args, tracer, config, defaultFieldResolver) {
222
+ args[3] = args[3] || {} // contextValue
223
+ args[6] = wrapResolve(args[6] || defaultFieldResolver, tracer, config) // fieldResolver
224
+ args.length = Math.max(args.length, 7)
219
225
 
220
226
  return {
221
227
  schema: args[0],
@@ -48,7 +48,7 @@ function createWrapMakeClientConstructor (tracer, config) {
48
48
  function wrapPackageDefinition (tracer, config, def) {
49
49
  for (const name in def) {
50
50
  if (def[name].format) continue
51
- if (def[name].service) {
51
+ if (def[name].service && def[name].prototype) {
52
52
  wrapClientConstructor(tracer, config, def[name], def[name].service)
53
53
  } else {
54
54
  wrapPackageDefinition(tracer, config, def[name])
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const web = require('../../dd-trace/src/plugins/util/web')
4
- const Scope = require('../../dd-trace/src/scope/base')
4
+ const Scope = require('../../dd-trace/src/scope')
5
5
 
6
6
  function createWrapEmit (tracer, config) {
7
7
  config = web.normalizeConfig(config)
@@ -5,13 +5,16 @@ const {
5
5
  TEST_NAME,
6
6
  TEST_SUITE,
7
7
  TEST_STATUS,
8
+ TEST_FRAMEWORK_VERSION,
9
+ JEST_TEST_RUNNER,
8
10
  ERROR_MESSAGE,
9
11
  ERROR_TYPE,
10
12
  TEST_PARAMETERS,
11
13
  CI_APP_ORIGIN,
12
14
  getTestEnvironmentMetadata,
13
15
  getTestParametersString,
14
- finishAllTraceSpans
16
+ finishAllTraceSpans,
17
+ getTestSuitePath
15
18
  } = require('../../dd-trace/src/plugins/util/test')
16
19
  const {
17
20
  getFormattedJestTestParameters,
@@ -30,7 +33,7 @@ function wrapEnvironment (BaseEnvironment) {
30
33
  return class DatadogJestEnvironment extends BaseEnvironment {
31
34
  constructor (config, context) {
32
35
  super(config, context)
33
- this.testSuite = context.testPath.replace(`${config.rootDir}/`, '')
36
+ this.testSuite = getTestSuitePath(context.testPath, config.rootDir)
34
37
  this.testSpansByTestName = {}
35
38
  this.originalTestFnByTestName = {}
36
39
  }
@@ -137,7 +140,9 @@ function createHandleTestEvent (tracer, testEnvironmentMetadata, instrumenter) {
137
140
  const spanTags = {
138
141
  ...commonSpanTags,
139
142
  [TEST_NAME]: testName,
140
- [TEST_SUITE]: this.testSuite
143
+ [TEST_SUITE]: this.testSuite,
144
+ [TEST_FRAMEWORK_VERSION]: tracer._version,
145
+ [JEST_TEST_RUNNER]: 'jest-circus'
141
146
  }
142
147
 
143
148
  const testParametersString = getTestParametersString(nameToParams, event.test.name)
@@ -5,9 +5,12 @@ const {
5
5
  TEST_NAME,
6
6
  TEST_SUITE,
7
7
  TEST_STATUS,
8
+ TEST_FRAMEWORK_VERSION,
9
+ JEST_TEST_RUNNER,
8
10
  CI_APP_ORIGIN,
9
11
  getTestEnvironmentMetadata,
10
- finishAllTraceSpans
12
+ finishAllTraceSpans,
13
+ getTestSuitePath
11
14
  } = require('../../dd-trace/src/plugins/util/test')
12
15
  const { getTestSpanTags, setSuppressedErrors } = require('./util')
13
16
 
@@ -21,14 +24,19 @@ function createWrapIt (tracer, globalConfig, globalInput, testEnvironmentMetadat
21
24
 
22
25
  const { childOf, commonSpanTags } = getTestSpanTags(tracer, testEnvironmentMetadata)
23
26
 
24
- const testSuite = globalInput.jasmine.testPath.replace(`${globalConfig.rootDir}/`, '')
27
+ const testSuite = getTestSuitePath(globalInput.jasmine.testPath, globalConfig.rootDir)
25
28
 
26
29
  const newSpecFunction = tracer.wrap(
27
30
  'jest.test',
28
31
  {
29
32
  type: 'test',
30
33
  childOf,
31
- tags: { ...commonSpanTags, [TEST_SUITE]: testSuite }
34
+ tags: {
35
+ ...commonSpanTags,
36
+ [TEST_SUITE]: testSuite,
37
+ [TEST_FRAMEWORK_VERSION]: tracer._version,
38
+ [JEST_TEST_RUNNER]: 'jest-jasmine2'
39
+ }
32
40
  },
33
41
  async (done) => {
34
42
  const testSpan = tracer.scope().active()
@@ -107,7 +115,7 @@ function createWrapItSkip (tracer, globalConfig, globalInput, testEnvironmentMet
107
115
  return function itSkipWithTrace () {
108
116
  const { childOf, commonSpanTags } = getTestSpanTags(tracer, testEnvironmentMetadata)
109
117
 
110
- const testSuite = globalInput.jasmine.testPath.replace(`${globalConfig.rootDir}/`, '')
118
+ const testSuite = getTestSuitePath(globalInput.jasmine.testPath, globalConfig.rootDir)
111
119
 
112
120
  const spec = it.apply(this, arguments)
113
121
 
@@ -123,7 +131,9 @@ function createWrapItSkip (tracer, globalConfig, globalInput, testEnvironmentMet
123
131
  [RESOURCE_NAME]: resource,
124
132
  [TEST_NAME]: testName,
125
133
  [TEST_SUITE]: testSuite,
126
- [TEST_STATUS]: 'skip'
134
+ [TEST_STATUS]: 'skip',
135
+ [TEST_FRAMEWORK_VERSION]: tracer._version,
136
+ [JEST_TEST_RUNNER]: 'jest-jasmine2'
127
137
  }
128
138
  }
129
139
  )
@@ -9,34 +9,43 @@ const {
9
9
  TEST_SUITE,
10
10
  TEST_STATUS,
11
11
  TEST_PARAMETERS,
12
+ TEST_FRAMEWORK_VERSION,
12
13
  CI_APP_ORIGIN,
13
14
  getTestEnvironmentMetadata,
14
15
  getTestParametersString,
15
16
  finishAllTraceSpans,
16
- getTestParentSpan
17
+ getTestParentSpan,
18
+ getTestSuitePath
17
19
  } = require('../../dd-trace/src/plugins/util/test')
18
20
 
19
21
  function getTestSpanMetadata (tracer, test, sourceRoot) {
20
22
  const childOf = getTestParentSpan(tracer)
21
23
 
22
- const { file: testSuite } = test
24
+ const { file: testSuiteAbsolutePath } = test
23
25
  const fullTestName = test.fullTitle()
24
- const strippedTestSuite = testSuite ? testSuite.replace(`${sourceRoot}/`, '') : ''
26
+ const testSuite = getTestSuitePath(testSuiteAbsolutePath, sourceRoot)
25
27
 
26
28
  return {
27
29
  childOf,
28
- resource: `${strippedTestSuite}.${fullTestName}`,
30
+ resource: `${testSuite}.${fullTestName}`,
29
31
  [TEST_TYPE]: 'test',
30
32
  [TEST_NAME]: fullTestName,
31
- [TEST_SUITE]: strippedTestSuite,
33
+ [TEST_SUITE]: testSuite,
32
34
  [SAMPLING_RULE_DECISION]: 1,
33
- [SAMPLING_PRIORITY]: AUTO_KEEP
35
+ [SAMPLING_PRIORITY]: AUTO_KEEP,
36
+ [TEST_FRAMEWORK_VERSION]: tracer._version
34
37
  }
35
38
  }
36
39
 
37
40
  function createWrapRunTest (tracer, testEnvironmentMetadata, sourceRoot) {
38
41
  return function wrapRunTest (runTest) {
39
42
  return async function runTestWithTrace () {
43
+ // `runTest` is rerun when retries are configured through `this.retries` and the test fails.
44
+ // This clause prevents rewrapping `this.test.fn` when it has already been wrapped.
45
+ if (this.test._currentRetry !== undefined && this.test._currentRetry !== 0) {
46
+ return runTest.apply(this, arguments)
47
+ }
48
+
40
49
  let specFunction = this.test.fn
41
50
  if (specFunction.length) {
42
51
  specFunction = promisify(specFunction)
@@ -4,6 +4,8 @@ module.exports = {
4
4
  HTTP_INCOMING_URL: 'server.request.uri.raw',
5
5
  HTTP_INCOMING_HEADERS: 'server.request.headers.no_cookies',
6
6
  HTTP_INCOMING_METHOD: 'server.request.method',
7
- HTTP_INCOMING_REMOTE_IP: 'server.request.remote_ip',
8
- HTTP_INCOMING_REMOTE_PORT: 'server.request.remote_port'
7
+ HTTP_INCOMING_REMOTE_IP: 'server.request.client_ip',
8
+ HTTP_INCOMING_REMOTE_PORT: 'server.request.client_port',
9
+ HTTP_INCOMING_RESPONSE_CODE: 'server.response.status',
10
+ HTTP_INCOMING_RESPONSE_HEADERS: 'server.response.headers.no_cookies'
9
11
  }