dd-trace 3.17.1 → 3.19.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/LICENSE-3rdparty.csv +1 -1
  2. package/esbuild.js +3 -0
  3. package/index.d.ts +10 -9
  4. package/package.json +12 -12
  5. package/packages/datadog-core/src/storage/async_resource.js +1 -1
  6. package/packages/datadog-esbuild/index.js +9 -2
  7. package/packages/datadog-instrumentations/src/body-parser.js +15 -9
  8. package/packages/datadog-instrumentations/src/cucumber.js +11 -1
  9. package/packages/datadog-instrumentations/src/express.js +32 -0
  10. package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
  11. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  12. package/packages/datadog-instrumentations/src/http/server.js +2 -1
  13. package/packages/datadog-instrumentations/src/jest.js +6 -3
  14. package/packages/datadog-instrumentations/src/mocha.js +19 -2
  15. package/packages/datadog-instrumentations/src/playwright.js +5 -2
  16. package/packages/datadog-plugin-amqp10/src/consumer.js +1 -3
  17. package/packages/datadog-plugin-amqp10/src/producer.js +1 -3
  18. package/packages/datadog-plugin-amqplib/src/client.js +4 -3
  19. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
  20. package/packages/datadog-plugin-amqplib/src/producer.js +1 -3
  21. package/packages/datadog-plugin-cucumber/src/index.js +6 -4
  22. package/packages/datadog-plugin-cypress/src/plugin.js +5 -1
  23. package/packages/datadog-plugin-cypress/src/support.js +4 -0
  24. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -3
  25. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -3
  26. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -3
  27. package/packages/datadog-plugin-http/src/client.js +1 -1
  28. package/packages/datadog-plugin-http/src/server.js +2 -2
  29. package/packages/datadog-plugin-http2/src/server.js +0 -5
  30. package/packages/datadog-plugin-jest/src/index.js +10 -5
  31. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -4
  32. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -3
  33. package/packages/datadog-plugin-mocha/src/index.js +9 -4
  34. package/packages/datadog-plugin-playwright/src/index.js +6 -5
  35. package/packages/datadog-plugin-redis/src/index.js +16 -5
  36. package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
  37. package/packages/datadog-plugin-rhea/src/producer.js +1 -5
  38. package/packages/dd-trace/src/appsec/addresses.js +0 -3
  39. package/packages/dd-trace/src/appsec/blocked_templates.js +2 -9
  40. package/packages/dd-trace/src/appsec/blocking.js +1 -1
  41. package/packages/dd-trace/src/appsec/{gateway/channels.js → channels.js} +4 -4
  42. package/packages/dd-trace/src/appsec/iast/index.js +1 -1
  43. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +21 -13
  44. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  45. package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +1 -1
  46. package/packages/dd-trace/src/appsec/index.js +87 -79
  47. package/packages/dd-trace/src/appsec/recommended.json +448 -121
  48. package/packages/dd-trace/src/appsec/remote_config/apply_states.js +7 -0
  49. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -0
  50. package/packages/dd-trace/src/appsec/remote_config/index.js +30 -11
  51. package/packages/dd-trace/src/appsec/remote_config/manager.js +33 -12
  52. package/packages/dd-trace/src/appsec/reporter.js +27 -58
  53. package/packages/dd-trace/src/appsec/rule_manager.js +160 -32
  54. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +4 -12
  55. package/packages/dd-trace/src/appsec/waf/index.js +75 -0
  56. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +57 -0
  57. package/packages/dd-trace/src/appsec/waf/waf_manager.js +66 -0
  58. package/packages/dd-trace/src/config.js +18 -1
  59. package/packages/dd-trace/src/dcitm.js +2 -0
  60. package/packages/dd-trace/src/encode/0.4.js +12 -4
  61. package/packages/dd-trace/src/encode/tags-processors.js +40 -68
  62. package/packages/dd-trace/src/exporters/common/request.js +2 -2
  63. package/packages/dd-trace/src/format.js +2 -1
  64. package/packages/dd-trace/src/iitm.js +1 -1
  65. package/packages/dd-trace/src/log/channels.js +11 -12
  66. package/packages/dd-trace/src/opentracing/propagation/text_map.js +2 -2
  67. package/packages/dd-trace/src/plugin_manager.js +3 -1
  68. package/packages/dd-trace/src/plugins/client.js +3 -2
  69. package/packages/dd-trace/src/plugins/consumer.js +17 -2
  70. package/packages/dd-trace/src/plugins/inbound.js +7 -0
  71. package/packages/dd-trace/src/plugins/{outgoing.js → outbound.js} +2 -2
  72. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  73. package/packages/dd-trace/src/plugins/producer.js +17 -2
  74. package/packages/dd-trace/src/plugins/server.js +2 -2
  75. package/packages/dd-trace/src/plugins/tracing.js +11 -0
  76. package/packages/dd-trace/src/plugins/util/test.js +19 -1
  77. package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -1
  78. package/packages/dd-trace/src/ritm.js +1 -1
  79. package/packages/dd-trace/src/service-naming/index.js +41 -0
  80. package/packages/dd-trace/src/service-naming/schemas/definition.js +28 -0
  81. package/packages/dd-trace/src/service-naming/schemas/index.js +6 -0
  82. package/packages/dd-trace/src/service-naming/schemas/v0.js +66 -0
  83. package/packages/dd-trace/src/service-naming/schemas/v1.js +58 -0
  84. package/packages/dd-trace/src/span_stats.js +1 -1
  85. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  86. package/packages/dd-trace/src/telemetry/index.js +1 -1
  87. package/packages/diagnostics_channel/index.js +3 -0
  88. package/packages/diagnostics_channel/src/index.js +57 -0
  89. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +0 -137
  90. package/packages/dd-trace/src/appsec/callbacks/index.js +0 -7
  91. package/packages/dd-trace/src/appsec/gateway/als.js +0 -6
  92. package/packages/dd-trace/src/appsec/gateway/engine/engine.js +0 -140
  93. package/packages/dd-trace/src/appsec/gateway/engine/index.js +0 -51
  94. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -42
  95. package/packages/dd-trace/src/instrumenter.js +0 -203
  96. package/packages/dd-trace/src/loader.js +0 -131
  97. package/packages/dd-trace/src/plugins/incoming.js +0 -7
@@ -41,6 +41,7 @@ dev,eslint,MIT,Copyright JS Foundation and other contributors https://js.foundat
41
41
  dev,eslint-config-standard,MIT,Copyright Feross Aboukhadijeh
42
42
  dev,eslint-plugin-import,MIT,Copyright 2015 Ben Mosher
43
43
  dev,eslint-plugin-mocha,MIT,Copyright 2014 Mathias Schreck
44
+ dev,eslint-plugin-n,MIT,Copyright 2015 Toru Nagashima
44
45
  dev,eslint-plugin-node,MIT,Copyright 2015 Toru Nagashima
45
46
  dev,eslint-plugin-promise,ISC,jden and other contributors
46
47
  dev,eslint-plugin-standard,MIT,Copyright 2015 Jamund Ferguson
@@ -63,6 +64,5 @@ dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
63
64
  dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
64
65
  dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
65
66
  dev,tape,MIT,Copyright James Halliday
66
- dev,wait-on,MIT,Copyright 2015 Jeff Barczewski
67
67
  file,aws-lambda-nodejs-runtime-interface-client,Apache 2.0,Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
68
68
  file,profile.proto,Apache license 2.0,Copyright 2016 Google Inc.
package/esbuild.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict'
2
+
3
+ module.exports = require('./packages/datadog-esbuild/index.js')
package/index.d.ts CHANGED
@@ -871,7 +871,7 @@ declare namespace plugins {
871
871
  /**
872
872
  * Hook to execute just before the request span finishes.
873
873
  */
874
- request?: (span?: opentracing.Span, req?: IncomingMessage, res?: ServerResponse) => any;
874
+ request?: (span?: Span, req?: IncomingMessage, res?: ServerResponse) => any;
875
875
  };
876
876
 
877
877
  /**
@@ -907,7 +907,7 @@ declare namespace plugins {
907
907
  /**
908
908
  * Hook to execute just before the request span finishes.
909
909
  */
910
- request?: (span?: opentracing.Span, req?: ClientRequest, res?: IncomingMessage) => any;
910
+ request?: (span?: Span, req?: ClientRequest, res?: IncomingMessage) => any;
911
911
  };
912
912
 
913
913
  /**
@@ -997,7 +997,7 @@ declare namespace plugins {
997
997
  /**
998
998
  * Hook to execute just before the aws span finishes.
999
999
  */
1000
- request?: (span?: opentracing.Span, response?: anyObject) => any;
1000
+ request?: (span?: Span, response?: anyObject) => any;
1001
1001
  };
1002
1002
 
1003
1003
  /**
@@ -1066,7 +1066,7 @@ declare namespace plugins {
1066
1066
  /**
1067
1067
  * Hook to execute just before the query span finishes.
1068
1068
  */
1069
- query?: (span?: opentracing.Span, params?: TransportRequestParams) => any;
1069
+ query?: (span?: Span, params?: TransportRequestParams) => any;
1070
1070
  };
1071
1071
  }
1072
1072
 
@@ -1166,7 +1166,8 @@ declare namespace plugins {
1166
1166
 
1167
1167
  /**
1168
1168
  * Whether to enable signature calculation for the resource name. This can
1169
- * be disabled if your GraphQL operations always have a name.
1169
+ * be disabled if your GraphQL operations always have a name. Note that when
1170
+ * disabled all queries will need to be named for this to work properly.
1170
1171
  *
1171
1172
  * @default true
1172
1173
  */
@@ -1235,7 +1236,7 @@ declare namespace plugins {
1235
1236
  * Hook to execute just before the request span finishes.
1236
1237
  */
1237
1238
  request?: (
1238
- span?: opentracing.Span,
1239
+ span?: Span,
1239
1240
  req?: IncomingMessage | ClientRequest,
1240
1241
  res?: ServerResponse | IncomingMessage
1241
1242
  ) => any;
@@ -1428,7 +1429,7 @@ declare namespace plugins {
1428
1429
  /**
1429
1430
  * Hook to execute just before the request span finishes.
1430
1431
  */
1431
- request?: (span?: opentracing.Span, req?: IncomingMessage, res?: ServerResponse) => any;
1432
+ request?: (span?: Span, req?: IncomingMessage, res?: ServerResponse) => any;
1432
1433
  };
1433
1434
  }
1434
1435
 
@@ -1547,12 +1548,12 @@ declare namespace plugins {
1547
1548
  /**
1548
1549
  * Hook to execute just when the span is created.
1549
1550
  */
1550
- receive?: (span?: opentracing.Span, request?: any) => any;
1551
+ receive?: (span?: Span, request?: any) => any;
1551
1552
 
1552
1553
  /**
1553
1554
  * Hook to execute just when the span is finished.
1554
1555
  */
1555
- reply?: (span?: opentracing.Span, request?: any, response?: any) => any;
1556
+ reply?: (span?: Span, request?: any, response?: any) => any;
1556
1557
  };
1557
1558
  }
1558
1559
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "3.17.1",
3
+ "version": "3.19.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -15,10 +15,10 @@
15
15
  "lint": "node scripts/check_licenses.js && eslint . && yarn audit --groups dependencies",
16
16
  "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
17
17
  "test": "SERVICES=* yarn services && mocha --colors --exit --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
18
- "test:appsec": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" --exclude \"packages/dd-trace/test/appsec/iast/**/*.plugin.spec.js\" \"packages/dd-trace/test/appsec/**/*.spec.js\"",
19
- "test:appsec:ci": "nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" --exclude \"packages/dd-trace/test/appsec/iast/**/*.plugin.spec.js\" -- npm run test:appsec",
20
- "test:appsec:plugins": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/appsec/iast/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
21
- "test:appsec:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/test/appsec/iast/**/*.@($(echo $PLUGINS)).plugin.spec.js\" -- npm run test:appsec:plugins",
18
+ "test:appsec": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" \"packages/dd-trace/test/appsec/**/*.spec.js\"",
19
+ "test:appsec:ci": "nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" -- npm run test:appsec",
20
+ "test:appsec:plugins": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
21
+ "test:appsec:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\" -- npm run test:appsec:plugins",
22
22
  "test:trace:core": "tap packages/dd-trace/test/*.spec.js \"packages/dd-trace/test/{ci-visibility,encode,exporters,opentracing,plugins,telemetry}/**/*.spec.js\"",
23
23
  "test:trace:core:ci": "npm run test:trace:core -- --coverage --nyc-arg=--include=\"packages/dd-trace/src/**/*.js\"",
24
24
  "test:instrumentations": "mocha --colors -r 'packages/dd-trace/test/setup/mocha.js' 'packages/datadog-instrumentations/test/**/*.spec.js'",
@@ -65,16 +65,16 @@
65
65
  "node": ">=14"
66
66
  },
67
67
  "dependencies": {
68
- "@datadog/native-appsec": "2.0.0",
68
+ "@datadog/native-appsec": "^3.1.0",
69
69
  "@datadog/native-iast-rewriter": "2.0.1",
70
- "@datadog/native-iast-taint-tracking": "1.3.1",
71
- "@datadog/native-metrics": "^1.5.0",
72
- "@datadog/pprof": "^2.1.0",
70
+ "@datadog/native-iast-taint-tracking": "^1.4.0",
71
+ "@datadog/native-metrics": "^1.6.0",
72
+ "@datadog/pprof": "^2.2.0",
73
73
  "@datadog/sketches-js": "^2.1.0",
74
74
  "crypto-randomuuid": "^1.0.0",
75
75
  "diagnostics_channel": "^1.1.0",
76
76
  "ignore": "^5.2.0",
77
- "import-in-the-middle": "^1.3.4",
77
+ "import-in-the-middle": "^1.3.5",
78
78
  "ipaddr.js": "^2.0.1",
79
79
  "istanbul-lib-coverage": "3.2.0",
80
80
  "koalas": "^1.0.2",
@@ -109,6 +109,7 @@
109
109
  "eslint-config-standard": "^11.0.0-beta.0",
110
110
  "eslint-plugin-import": "^2.8.0",
111
111
  "eslint-plugin-mocha": "^10.1.0",
112
+ "eslint-plugin-n": "^15.7.0",
112
113
  "eslint-plugin-node": "^5.2.1",
113
114
  "eslint-plugin-promise": "^3.6.0",
114
115
  "eslint-plugin-standard": "^3.0.1",
@@ -130,7 +131,6 @@
130
131
  "sinon": "^11.1.2",
131
132
  "sinon-chai": "^3.7.0",
132
133
  "tap": "^16.3.4",
133
- "tape": "^4.9.1",
134
- "wait-on": "^5.0.0"
134
+ "tape": "^4.9.1"
135
135
  }
136
136
  }
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { createHook, executionAsyncResource } = require('async_hooks')
4
- const { channel } = require('diagnostics_channel')
4
+ const { channel } = require('../../../diagnostics_channel')
5
5
 
6
6
  const beforeCh = channel('dd-trace:storage:before')
7
7
  const afterCh = channel('dd-trace:storage:after')
@@ -93,11 +93,18 @@ module.exports.setup = function (build) {
93
93
  })
94
94
  }
95
95
 
96
+ // Currently esbuild support requires Node.js >=v16.17 or >=v18.7
97
+ // Better yet it would support Node >=v14.17 or >=v16
98
+ // Of course, the most ideal would be to support all versions of Node that dd-trace supports.
99
+ // Version constraints based on Node's diagnostics_channel support
96
100
  function warnIfUnsupported () {
97
101
  const [major, minor] = process.versions.node.split('.').map(Number)
98
- if (major < 14 || (major === 14 && minor < 17)) {
102
+ if (
103
+ major < 16 ||
104
+ (major === 16 && minor < 17) ||
105
+ (major === 18 && minor < 7)) {
99
106
  console.error('WARNING: Esbuild support isn\'t available for older versions of Node.js.')
100
- console.error(`Expected: Node.js >= v14.17. Actual: Node.js = ${process.version}.`)
107
+ console.error(`Expected: Node.js >=v16.17 or >=v18.7. Actual: Node.js = ${process.version}.`)
101
108
  console.error('This application may build properly with this version of Node.js, but unless a')
102
109
  console.error('more recent version is used at runtime, third party packages won\'t be instrumented.')
103
110
  }
@@ -1,14 +1,21 @@
1
1
  'use strict'
2
2
 
3
- const { channel, addHook, AsyncResource } = require('./helpers/instrument')
3
+ const { AbortController } = require('node-abort-controller') // AbortController is not available in node <15
4
+ const shimmer = require('../../datadog-shimmer')
5
+ const { channel, addHook } = require('./helpers/instrument')
4
6
 
5
7
  const bodyParserReadCh = channel('datadog:body-parser:read:finish')
6
8
 
7
- function publishRequestBodyAndNext (request, next) {
9
+ function publishRequestBodyAndNext (req, res, next) {
8
10
  return function () {
9
- if (bodyParserReadCh.hasSubscribers && request) {
10
- bodyParserReadCh.publish({ request })
11
+ if (bodyParserReadCh.hasSubscribers && req) {
12
+ const abortController = new AbortController()
13
+
14
+ bodyParserReadCh.publish({ req, res, abortController })
15
+
16
+ if (abortController.signal.aborted) return
11
17
  }
18
+
12
19
  next.apply(this, arguments)
13
20
  }
14
21
  }
@@ -16,11 +23,10 @@ function publishRequestBodyAndNext (request, next) {
16
23
  addHook({
17
24
  name: 'body-parser',
18
25
  file: 'lib/read.js',
19
- versions: ['>=1']
26
+ versions: ['>=1.4.0']
20
27
  }, read => {
21
- return function (req, res, next) {
22
- const nextResource = new AsyncResource('bound-anonymous-fn')
23
- arguments[2] = nextResource.bind(publishRequestBodyAndNext(req, next))
28
+ return shimmer.wrap(read, function (req, res, next) {
29
+ arguments[2] = publishRequestBodyAndNext(req, res, next)
24
30
  read.apply(this, arguments)
25
- }
31
+ })
26
32
  })
@@ -90,7 +90,17 @@ function wrapRun (pl, isLatestVersion) {
90
90
  if (!pickleResultByFile[testSuiteFullPath]) { // first test in suite
91
91
  testSuiteStartCh.publish(testSuiteFullPath)
92
92
  }
93
- testStartCh.publish({ testName: this.pickle.name, fullTestSuite: testSuiteFullPath })
93
+
94
+ const testSourceLine = this.gherkinDocument &&
95
+ this.gherkinDocument.feature &&
96
+ this.gherkinDocument.feature.location &&
97
+ this.gherkinDocument.feature.location.line
98
+
99
+ testStartCh.publish({
100
+ testName: this.pickle.name,
101
+ fullTestSuite: testSuiteFullPath,
102
+ testSourceLine
103
+ })
94
104
  try {
95
105
  const promise = run.apply(this, arguments)
96
106
  promise.finally(() => {
@@ -3,6 +3,7 @@
3
3
  const { createWrapRouterMethod } = require('./router')
4
4
  const shimmer = require('../../datadog-shimmer')
5
5
  const { addHook, channel } = require('./helpers/instrument')
6
+ const { AbortController } = require('node-abort-controller')
6
7
 
7
8
  const handleChannel = channel('apm:express:request:handle')
8
9
 
@@ -25,3 +26,34 @@ addHook({ name: 'express', versions: ['>=4'] }, express => {
25
26
 
26
27
  return express
27
28
  })
29
+
30
+ const queryParserReadCh = channel('datadog:query:read:finish')
31
+
32
+ function publishQueryParsedAndNext (req, res, next) {
33
+ return function () {
34
+ if (queryParserReadCh.hasSubscribers && req) {
35
+ const abortController = new AbortController()
36
+
37
+ queryParserReadCh.publish({ req, res, abortController })
38
+
39
+ if (abortController.signal.aborted) return
40
+ }
41
+
42
+ next.apply(this, arguments)
43
+ }
44
+ }
45
+
46
+ addHook({
47
+ name: 'express',
48
+ versions: ['>=4'],
49
+ file: 'lib/middleware/query.js'
50
+ }, query => {
51
+ return shimmer.wrap(query, function () {
52
+ const queryMiddleware = query.apply(this, arguments)
53
+
54
+ return shimmer.wrap(queryMiddleware, function (req, res, next) {
55
+ arguments[2] = publishQueryParsedAndNext(req, res, next)
56
+ return queryMiddleware.apply(this, arguments)
57
+ })
58
+ })
59
+ })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const dc = require('diagnostics_channel')
3
+ const dc = require('../../../diagnostics_channel')
4
4
  const semver = require('semver')
5
5
  const instrumentations = require('./instrumentations')
6
6
  const { AsyncResource } = require('async_hooks')
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { channel } = require('diagnostics_channel')
3
+ const { channel } = require('../../../diagnostics_channel')
4
4
  const path = require('path')
5
5
  const semver = require('semver')
6
6
  const Hook = require('./hook')
@@ -55,7 +55,8 @@ function wrapEmit (emit) {
55
55
 
56
56
  try {
57
57
  if (abortController.signal.aborted) {
58
- return res.end()
58
+ // TODO: should this always return true ?
59
+ return this.listenerCount(eventName) > 0
59
60
  }
60
61
  return emit.apply(this, arguments)
61
62
  } catch (err) {
@@ -5,7 +5,8 @@ const log = require('../../dd-trace/src/log')
5
5
  const {
6
6
  getCoveredFilenamesFromCoverage,
7
7
  JEST_WORKER_TRACE_PAYLOAD_CODE,
8
- JEST_WORKER_COVERAGE_PAYLOAD_CODE
8
+ JEST_WORKER_COVERAGE_PAYLOAD_CODE,
9
+ getTestLineStart
9
10
  } = require('../../dd-trace/src/plugins/util/test')
10
11
 
11
12
  const testSessionStartCh = channel('ci:jest:session:start')
@@ -125,7 +126,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
125
126
  suite: this.testSuite,
126
127
  runner: 'jest-circus',
127
128
  testParameters,
128
- frameworkVersion: jestVersion
129
+ frameworkVersion: jestVersion,
130
+ testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
129
131
  })
130
132
  originalTestFns.set(event.test, event.test.fn)
131
133
  event.test.fn = asyncResource.bind(event.test.fn)
@@ -152,7 +154,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
152
154
  name: getJestTestName(event.test),
153
155
  suite: this.testSuite,
154
156
  runner: 'jest-circus',
155
- frameworkVersion: jestVersion
157
+ frameworkVersion: jestVersion,
158
+ testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
156
159
  })
157
160
  })
158
161
  }
@@ -9,7 +9,8 @@ const {
9
9
  resetCoverage,
10
10
  mergeCoverage,
11
11
  getTestSuitePath,
12
- fromCoverageMapToCoverage
12
+ fromCoverageMapToCoverage,
13
+ getTestLineStart
13
14
  } = require('../../dd-trace/src/plugins/util/test')
14
15
 
15
16
  const testStartCh = channel('ci:mocha:test:start')
@@ -35,6 +36,7 @@ const patched = new WeakSet()
35
36
  const testToAr = new WeakMap()
36
37
  const originalFns = new WeakMap()
37
38
  const testFileToSuiteAr = new Map()
39
+ const testToStartLine = new WeakMap()
38
40
 
39
41
  // `isWorker` is true if it's a Mocha worker
40
42
  let isWorker = false
@@ -207,10 +209,11 @@ function mochaHook (Runner) {
207
209
  if (isRetry(test)) {
208
210
  return
209
211
  }
212
+ const testStartLine = testToStartLine.get(test)
210
213
  const asyncResource = new AsyncResource('bound-anonymous-fn')
211
214
  testToAr.set(test.fn, asyncResource)
212
215
  asyncResource.runInAsyncScope(() => {
213
- testStartCh.publish(test)
216
+ testStartCh.publish({ test, testStartLine })
214
217
  })
215
218
  })
216
219
 
@@ -384,6 +387,20 @@ addHook({
384
387
  return Mocha
385
388
  })
386
389
 
390
+ addHook({
391
+ name: 'mocha',
392
+ versions: ['>=5.2.0'],
393
+ file: 'lib/suite.js'
394
+ }, (Suite) => {
395
+ shimmer.wrap(Suite.prototype, 'addTest', addTest => function (test) {
396
+ // In here, the test definition is in the stack, so we search for it.
397
+ const startLine = getTestLineStart(new Error(), test.file)
398
+ testToStartLine.set(test, startLine)
399
+ return addTest.apply(this, arguments)
400
+ })
401
+ return Suite
402
+ })
403
+
387
404
  addHook({
388
405
  name: 'mocha',
389
406
  versions: ['>=5.2.0'],
@@ -72,11 +72,14 @@ function getRootDir (playwrightRunner) {
72
72
  if (playwrightRunner._configDir) {
73
73
  return playwrightRunner._configDir
74
74
  }
75
+ if (playwrightRunner._config && playwrightRunner._config.config) {
76
+ return playwrightRunner._config.config.rootDir
77
+ }
75
78
  return process.cwd()
76
79
  }
77
80
 
78
81
  function testBeginHandler (test) {
79
- const { _requireFile: testSuiteAbsolutePath, title: testName, _type } = test
82
+ const { _requireFile: testSuiteAbsolutePath, title: testName, _type, location: { line: testSourceLine } } = test
80
83
 
81
84
  if (_type === 'beforeAll' || _type === 'afterAll') {
82
85
  return
@@ -96,7 +99,7 @@ function testBeginHandler (test) {
96
99
  const testAsyncResource = new AsyncResource('bound-anonymous-fn')
97
100
  testToAr.set(test, testAsyncResource)
98
101
  testAsyncResource.runInAsyncScope(() => {
99
- testStartCh.publish({ testName, testSuiteAbsolutePath })
102
+ testStartCh.publish({ testName, testSuiteAbsolutePath, testSourceLine })
100
103
  })
101
104
  }
102
105
 
@@ -11,11 +11,9 @@ class Amqp10ConsumerPlugin extends ConsumerPlugin {
11
11
  const source = getShortName(link)
12
12
  const address = getAddress(link)
13
13
 
14
- this.startSpan('amqp.receive', {
15
- service: this.config.service || `${this.tracer._service}-amqp`,
14
+ this.startSpan({
16
15
  resource: ['receive', source].filter(v => v).join(' '),
17
16
  type: 'worker',
18
- kind: 'consumer',
19
17
  meta: {
20
18
  'amqp.link.source.address': source,
21
19
  'amqp.link.role': 'receiver',
@@ -13,10 +13,8 @@ class Amqp10ProducerPlugin extends ProducerPlugin {
13
13
  const address = getAddress(link)
14
14
  const target = getShortName(link)
15
15
 
16
- this.startSpan('amqp.send', {
17
- service: this.config.service || `${this.tracer._service}-amqp`,
16
+ this.startSpan({
18
17
  resource: ['send', target].filter(v => v).join(' '),
19
- kind: 'producer',
20
18
  meta: {
21
19
  'amqp.link.target.address': target,
22
20
  'amqp.link.role': 'sender',
@@ -7,6 +7,7 @@ const { getResourceName } = require('./util')
7
7
 
8
8
  class AmqplibClientPlugin extends ClientPlugin {
9
9
  static get id () { return 'amqplib' }
10
+ static get type () { return 'messaging' }
10
11
  static get operation () { return 'command' }
11
12
 
12
13
  start ({ channel = {}, method, fields }) {
@@ -14,10 +15,10 @@ class AmqplibClientPlugin extends ClientPlugin {
14
15
  if (method === 'basic.publish') return
15
16
 
16
17
  const stream = (channel.connection && channel.connection.stream) || {}
17
- const span = this.startSpan('amqp.command', {
18
- service: this.config.service || `${this.tracer._service}-amqp`,
18
+ const span = this.startSpan(this.operationName(), {
19
+ service: this.config.service || this.serviceName(),
19
20
  resource: getResourceName(method, fields),
20
- kind: 'client',
21
+ kind: this.constructor.kind,
21
22
  meta: {
22
23
  'out.host': stream._host,
23
24
  [CLIENT_PORT_KEY]: stream.remotePort,
@@ -13,11 +13,9 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
13
13
 
14
14
  const childOf = extract(this.tracer, message)
15
15
 
16
- this.startSpan('amqp.command', {
16
+ this.startSpan({
17
17
  childOf,
18
- service: this.config.service || `${this.tracer._service}-amqp`,
19
18
  resource: getResourceName(method, fields),
20
- kind: 'consumer',
21
19
  type: 'worker',
22
20
  meta: {
23
21
  'amqp.queue': fields.queue,
@@ -13,10 +13,8 @@ class AmqplibProducerPlugin extends ProducerPlugin {
13
13
  if (method !== 'basic.publish') return
14
14
 
15
15
  const stream = (channel.connection && channel.connection.stream) || {}
16
- const span = this.startSpan('amqp.command', {
17
- service: this.config.service || `${this.tracer._service}-amqp`,
16
+ const span = this.startSpan({
18
17
  resource: getResourceName(method, fields),
19
- kind: 'producer',
20
18
  meta: {
21
19
  'out.host': stream._host,
22
20
  [CLIENT_PORT_KEY]: stream.remotePort,
@@ -6,6 +6,7 @@ const { storage } = require('../../datadog-core')
6
6
  const {
7
7
  TEST_SKIP_REASON,
8
8
  TEST_STATUS,
9
+ TEST_SOURCE_START,
9
10
  finishAllTraceSpans,
10
11
  getTestSuitePath,
11
12
  getTestSuiteCommonTags,
@@ -80,10 +81,10 @@ class CucumberPlugin extends CiPlugin {
80
81
  this.tracer._exporter.exportCoverage(formattedCoverage)
81
82
  })
82
83
 
83
- this.addSub('ci:cucumber:test:start', ({ testName, fullTestSuite }) => {
84
+ this.addSub('ci:cucumber:test:start', ({ testName, fullTestSuite, testSourceLine }) => {
84
85
  const store = storage.getStore()
85
86
  const testSuite = getTestSuitePath(fullTestSuite, this.sourceRoot)
86
- const testSpan = this.startTestSpan(testName, testSuite)
87
+ const testSpan = this.startTestSpan(testName, testSuite, testSourceLine)
87
88
 
88
89
  this.enter(testSpan, store)
89
90
  })
@@ -130,11 +131,12 @@ class CucumberPlugin extends CiPlugin {
130
131
  })
131
132
  }
132
133
 
133
- startTestSpan (testName, testSuite) {
134
+ startTestSpan (testName, testSuite, testSourceLine) {
134
135
  return super.startTestSpan(
135
136
  testName,
136
137
  testSuite,
137
- this.testSuiteSpan
138
+ this.testSuiteSpan,
139
+ { [TEST_SOURCE_START]: testSourceLine }
138
140
  )
139
141
  }
140
142
  }
@@ -16,6 +16,7 @@ const {
16
16
  TEST_SESSION_ID,
17
17
  TEST_COMMAND,
18
18
  TEST_MODULE,
19
+ TEST_SOURCE_START,
19
20
  finishAllTraceSpans
20
21
  } = require('../../dd-trace/src/plugins/util/test')
21
22
 
@@ -204,7 +205,7 @@ module.exports = (on, config) => {
204
205
  return activeSpan ? activeSpan.context().toTraceId() : null
205
206
  },
206
207
  'dd:afterEach': (test) => {
207
- const { state, error, isRUMActive } = test
208
+ const { state, error, isRUMActive, testSourceLine } = test
208
209
  if (activeSpan) {
209
210
  activeSpan.setTag(TEST_STATUS, CYPRESS_STATUS_TO_TEST_STATUS[state])
210
211
  if (error) {
@@ -213,6 +214,9 @@ module.exports = (on, config) => {
213
214
  if (isRUMActive) {
214
215
  activeSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
215
216
  }
217
+ if (testSourceLine) {
218
+ activeSpan.setTag(TEST_SOURCE_START, testSourceLine)
219
+ }
216
220
  activeSpan.finish()
217
221
  }
218
222
  activeSpan = null
@@ -29,6 +29,10 @@ afterEach(() => {
29
29
  state: currentTest.state,
30
30
  error: currentTest.err,
31
31
  }
32
+ try {
33
+ testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
34
+ } catch (e) {}
35
+
32
36
  if (win.DD_RUM) {
33
37
  testInfo.isRUMActive = true
34
38
  }
@@ -4,15 +4,16 @@ const ClientPlugin = require('../../dd-trace/src/plugins/client')
4
4
 
5
5
  class GoogleCloudPubsubClientPlugin extends ClientPlugin {
6
6
  static get id () { return 'google-cloud-pubsub' }
7
+ static get type () { return 'messaging' }
7
8
  static get operation () { return 'request' }
8
9
 
9
10
  start ({ request, api, projectId }) {
10
11
  if (api === 'publish') return
11
12
 
12
- this.startSpan('pubsub.request', {
13
- service: this.config.service || `${this.tracer._service}-pubsub`,
13
+ this.startSpan(this.operationName(), {
14
+ service: this.config.service || this.serviceName(),
14
15
  resource: [api, request.name].filter(x => x).join(' '),
15
- kind: 'client',
16
+ kind: this.constructor.kind,
16
17
  meta: {
17
18
  'pubsub.method': api,
18
19
  'gcloud.project_id': projectId
@@ -11,11 +11,9 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
11
11
  const topic = subscription.metadata && subscription.metadata.topic
12
12
  const childOf = this.tracer.extract('text_map', message.attributes) || null
13
13
 
14
- this.startSpan('pubsub.receive', {
14
+ this.startSpan({
15
15
  childOf,
16
- service: this.config.service,
17
16
  resource: topic,
18
- kind: 'consumer',
19
17
  type: 'worker',
20
18
  meta: {
21
19
  'gcloud.project_id': subscription.pubsub.projectId,
@@ -11,10 +11,8 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
11
11
 
12
12
  const messages = request.messages || []
13
13
  const topic = request.topic
14
- const span = this.startSpan('pubsub.request', { // TODO: rename
15
- service: this.config.service || `${this.tracer._service}-pubsub`,
14
+ const span = this.startSpan({ // TODO: rename
16
15
  resource: `${api} ${topic}`,
17
- kind: 'producer',
18
16
  meta: {
19
17
  'gcloud.project_id': projectId,
20
18
  'pubsub.method': api, // TODO: remove
@@ -94,7 +94,7 @@ function errorHandler (err) {
94
94
  if (err) {
95
95
  span.addTags({
96
96
  [ERROR_TYPE]: err.name,
97
- [ERROR_MESSAGE]: err.message,
97
+ [ERROR_MESSAGE]: err.message || err.code,
98
98
  [ERROR_STACK]: err.stack
99
99
  })
100
100
  } else {