dd-trace 2.12.1 → 2.14.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 (61) hide show
  1. package/LICENSE-3rdparty.csv +1 -1
  2. package/ext/formats.js +3 -5
  3. package/package.json +5 -5
  4. package/packages/datadog-core/src/storage/async_resource.js +19 -1
  5. package/packages/datadog-instrumentations/index.js +1 -52
  6. package/packages/datadog-instrumentations/src/connect.js +1 -1
  7. package/packages/datadog-instrumentations/src/cucumber.js +15 -0
  8. package/packages/datadog-instrumentations/src/fs.js +11 -0
  9. package/packages/datadog-instrumentations/src/helpers/hooks.js +69 -0
  10. package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
  11. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
  12. package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
  13. package/packages/datadog-instrumentations/src/jest.js +33 -11
  14. package/packages/datadog-instrumentations/src/koa.js +1 -1
  15. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  16. package/packages/datadog-instrumentations/src/restify.js +27 -5
  17. package/packages/datadog-instrumentations/src/router.js +1 -1
  18. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
  19. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
  20. package/packages/datadog-plugin-cucumber/src/index.js +4 -0
  21. package/packages/datadog-plugin-fs/src/index.js +72 -38
  22. package/packages/datadog-plugin-jest/src/index.js +25 -4
  23. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  24. package/packages/datadog-plugin-mongodb-core/src/index.js +21 -6
  25. package/packages/datadog-plugin-oracledb/src/index.js +12 -4
  26. package/packages/datadog-plugin-restify/src/index.js +7 -0
  27. package/packages/dd-trace/index.js +1 -1
  28. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
  29. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
  30. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
  31. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +220 -0
  32. package/packages/dd-trace/src/config.js +13 -0
  33. package/packages/dd-trace/src/encode/0.4.js +55 -58
  34. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
  35. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
  36. package/packages/dd-trace/src/exporters/agent/index.js +13 -7
  37. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  38. package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
  39. package/packages/dd-trace/src/exporters/common/request.js +65 -39
  40. package/packages/dd-trace/src/exporters/common/writer.js +16 -6
  41. package/packages/dd-trace/src/id.js +16 -13
  42. package/packages/dd-trace/src/index.js +10 -0
  43. package/packages/dd-trace/src/noop/proxy.js +87 -0
  44. package/packages/dd-trace/src/noop/span.js +12 -12
  45. package/packages/dd-trace/src/noop/tracer.js +8 -5
  46. package/packages/dd-trace/src/opentracing/propagation/text_map.js +6 -6
  47. package/packages/dd-trace/src/opentracing/span.js +63 -49
  48. package/packages/dd-trace/src/opentracing/span_context.js +1 -5
  49. package/packages/dd-trace/src/opentracing/tracer.js +31 -36
  50. package/packages/dd-trace/src/plugin_manager.js +97 -65
  51. package/packages/dd-trace/src/plugins/index.js +58 -45
  52. package/packages/dd-trace/src/plugins/util/ci.js +34 -9
  53. package/packages/dd-trace/src/plugins/util/git.js +52 -2
  54. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  55. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  56. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  57. package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
  58. package/packages/dd-trace/src/proxy.js +18 -90
  59. package/packages/dd-trace/src/startup-log.js +8 -19
  60. package/packages/dd-trace/src/telemetry.js +2 -15
  61. package/scripts/install_plugin_modules.js +17 -26
@@ -8,6 +8,7 @@ require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
8
8
  require,diagnostics_channel,MIT,Copyright 2021 Simon D.
9
9
  require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
10
10
  require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
11
+ require,istanbul-lib-coverage,BSD-3-Clause,Copyright 2012-2015 Yahoo! Inc.
11
12
  require,koalas,MIT,Copyright 2013-2017 Brian Woodward
12
13
  require,limiter,MIT,Copyright 2011 John Hurliman
13
14
  require,lodash.kebabcase,MIT,Copyright JS Foundation and other contributors
@@ -18,7 +19,6 @@ require,methods,MIT,Copyright 2013-2014 TJ Holowaychuk
18
19
  require,module-details-from-path,MIT,Copyright 2016 Thomas Watson Steen
19
20
  require,opentracing,MIT,Copyright 2016 Resonance Labs Inc
20
21
  require,path-to-regexp,MIT,Copyright 2014 Blake Embrey
21
- require,performance-now,MIT,Copyright 2013 Braveg1rl
22
22
  require,retry,MIT,Copyright 2011 Tim Koschützki Felix Geisendörfer
23
23
  require,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
24
24
  dev,autocannon,MIT,Copyright 2016 Matteo Collina
package/ext/formats.js CHANGED
@@ -1,10 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const opentracing = require('opentracing')
4
-
5
3
  module.exports = {
6
- TEXT_MAP: opentracing.FORMAT_TEXT_MAP,
7
- HTTP_HEADERS: opentracing.FORMAT_HTTP_HEADERS,
8
- BINARY: opentracing.FORMAT_BINARY,
4
+ TEXT_MAP: 'text_map',
5
+ HTTP_HEADERS: 'http_headers',
6
+ BINARY: 'binary',
9
7
  LOG: 'log'
10
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "2.12.1",
3
+ "version": "2.14.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -59,14 +59,15 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@datadog/native-appsec": "^1.2.1",
62
- "@datadog/native-metrics": "^1.4.1",
63
- "@datadog/pprof": "^1.0.0",
64
- "@datadog/sketches-js": "^1.0.5",
62
+ "@datadog/native-metrics": "^1.4.2",
63
+ "@datadog/pprof": "^1.0.2",
64
+ "@datadog/sketches-js": "^2.0.0",
65
65
  "@types/node": ">=12",
66
66
  "crypto-randomuuid": "^1.0.0",
67
67
  "diagnostics_channel": "^1.1.0",
68
68
  "ignore": "^5.2.0",
69
69
  "import-in-the-middle": "^1.3.0",
70
+ "istanbul-lib-coverage": "3.2.0",
70
71
  "koalas": "^1.0.2",
71
72
  "limiter": "^1.1.4",
72
73
  "lodash.kebabcase": "^4.1.1",
@@ -77,7 +78,6 @@
77
78
  "module-details-from-path": "^1.0.3",
78
79
  "opentracing": ">=0.12.1",
79
80
  "path-to-regexp": "^0.1.2",
80
- "performance-now": "^2.1.0",
81
81
  "retry": "^0.10.1",
82
82
  "semver": "^5.5.0"
83
83
  },
@@ -6,9 +6,27 @@ const { channel } = require('diagnostics_channel')
6
6
  const beforeCh = channel('dd-trace:storage:before')
7
7
  const afterCh = channel('dd-trace:storage:after')
8
8
 
9
+ let PrivateSymbol = Symbol
10
+ function makePrivateSymbol () {
11
+ // eslint-disable-next-line no-new-func
12
+ PrivateSymbol = new Function('name', 'return %CreatePrivateSymbol(name)')
13
+ }
14
+
15
+ try {
16
+ makePrivateSymbol()
17
+ } catch (e) {
18
+ try {
19
+ const v8 = require('v8')
20
+ v8.setFlagsFromString('--allow-natives-syntax')
21
+ makePrivateSymbol()
22
+ v8.setFlagsFromString('--no-allow-natives-syntax')
23
+ // eslint-disable-next-line no-empty
24
+ } catch (e) {}
25
+ }
26
+
9
27
  class AsyncResourceStorage {
10
28
  constructor () {
11
- this._ddResourceStore = Symbol('ddResourceStore')
29
+ this._ddResourceStore = PrivateSymbol('ddResourceStore')
12
30
  this._enabled = false
13
31
  this._hook = createHook(this._createHook())
14
32
  }
@@ -1,54 +1,3 @@
1
1
  'use strict'
2
2
 
3
- require('./src/amqplib')
4
- require('./src/amqp10')
5
- require('./src/aws-sdk')
6
- require('./src/bluebird')
7
- require('./src/bunyan')
8
- require('./src/cassandra-driver')
9
- require('./src/connect')
10
- require('./src/couchbase')
11
- require('./src/cucumber')
12
- require('./src/dns')
13
- require('./src/elasticsearch')
14
- require('./src/express')
15
- require('./src/fastify')
16
- require('./src/find-my-way')
17
- require('./src/generic-pool')
18
- require('./src/google-cloud-pubsub')
19
- require('./src/graphql')
20
- require('./src/grpc')
21
- require('./src/hapi')
22
- require('./src/http')
23
- require('./src/http2')
24
- require('./src/ioredis')
25
- require('./src/jest')
26
- require('./src/kafkajs')
27
- require('./src/knex')
28
- require('./src/koa')
29
- require('./src/memcached')
30
- require('./src/microgateway-core')
31
- require('./src/moleculer')
32
- require('./src/mongodb-core')
33
- require('./src/mongoose')
34
- require('./src/mysql')
35
- require('./src/mysql2')
36
- require('./src/mocha')
37
- require('./src/net')
38
- require('./src/next')
39
- require('./src/oracledb')
40
- require('./src/paperplane')
41
- require('./src/pino')
42
- require('./src/pg')
43
- require('./src/promise')
44
- require('./src/promise-js')
45
- require('./src/q')
46
- require('./src/redis')
47
- require('./src/restify')
48
- require('./src/router')
49
- require('./src/rhea')
50
- require('./src/sharedb')
51
- require('./src/tedious')
52
- require('./src/when')
53
- require('./src/winston')
54
- require('./src/limitd-client')
3
+ require('./src/helpers/register')
@@ -98,7 +98,7 @@ function wrapNext (req, next) {
98
98
  nextChannel.publish({ req })
99
99
  exitChannel.publish({ req })
100
100
 
101
- next.apply(null, arguments)
101
+ next.apply(this, arguments)
102
102
  }
103
103
  }
104
104
 
@@ -7,6 +7,7 @@ const runStartCh = channel('ci:cucumber:run:start')
7
7
  const runFinishCh = channel('ci:cucumber:run:finish')
8
8
  const runStepStartCh = channel('ci:cucumber:run-step:start')
9
9
  const errorCh = channel('ci:cucumber:error')
10
+ const sessionFinishCh = channel('ci:cucumber:session:finish')
10
11
 
11
12
  // TODO: remove in a later major version
12
13
  const patched = new WeakSet()
@@ -128,4 +129,18 @@ addHook({
128
129
  file: 'lib/runtime/test_case_runner.js'
129
130
  }, testCaseHook)
130
131
 
132
+ addHook({
133
+ name: '@cucumber/cucumber',
134
+ versions: ['>=7.0.0'],
135
+ file: 'lib/runtime/index.js'
136
+ }, (Runtime) => {
137
+ shimmer.wrap(Runtime.default.prototype, 'start', start => async function () {
138
+ const result = await start.apply(this, arguments)
139
+ sessionFinishCh.publish(undefined)
140
+ return result
141
+ })
142
+
143
+ return Runtime
144
+ })
145
+
131
146
  module.exports = { pickleHook, testCaseHook }
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const { addHook, channel } = require('./helpers/instrument')
4
+
5
+ const hookChannel = channel('apm:fs:hook')
6
+
7
+ // HACK: trigger old style plugin
8
+ addHook({ name: 'fs' }, fs => {
9
+ hookChannel.publish(fs)
10
+ return fs
11
+ })
@@ -0,0 +1,69 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ '@cucumber/cucumber': () => require('../cucumber'),
5
+ '@elastic/elasticsearch': () => require('../elasticsearch'),
6
+ '@elastic/transport': () => require('../elasticsearch'),
7
+ '@google-cloud/pubsub': () => require('../google-cloud-pubsub'),
8
+ '@grpc/grpc-js': () => require('../grpc'),
9
+ '@hapi/hapi': () => require('../hapi'),
10
+ '@koa/router': () => require('../koa'),
11
+ '@node-redis/client': () => require('../redis'),
12
+ 'amqp10': () => require('../amqp10'),
13
+ 'amqplib': () => require('../amqplib'),
14
+ 'aws-sdk': () => require('../aws-sdk'),
15
+ 'bluebird': () => require('../bluebird'),
16
+ 'bunyan': () => require('../bunyan'),
17
+ 'cassandra-driver': () => require('../cassandra-driver'),
18
+ 'connect': () => require('../connect'),
19
+ 'couchbase': () => require('../couchbase'),
20
+ 'cypress': () => require('../cypress'),
21
+ 'dns': () => require('../dns'),
22
+ 'elasticsearch': () => require('../elasticsearch'),
23
+ 'express': () => require('../express'),
24
+ 'fastify': () => require('../fastify'),
25
+ 'find-my-way': () => require('../find-my-way'),
26
+ 'fs': () => require('../fs'),
27
+ 'graphql': () => require('../graphql'),
28
+ 'grpc': () => require('../grpc'),
29
+ 'hapi': () => require('../hapi'),
30
+ 'http': () => require('../http'),
31
+ 'http2': () => require('../http2'),
32
+ 'https': () => require('../http'),
33
+ 'ioredis': () => require('../ioredis'),
34
+ 'jest-environment-node': () => require('../jest'),
35
+ 'jest-environment-jsdom': () => require('../jest'),
36
+ 'jest-jasmine2': () => require('../jest'),
37
+ 'koa': () => require('../koa'),
38
+ 'koa-router': () => require('../koa'),
39
+ 'kafkajs': () => require('../kafkajs'),
40
+ 'limitd-client': () => require('../limitd-client'),
41
+ 'memcached': () => require('../memcached'),
42
+ 'microgateway-core': () => require('../microgateway-core'),
43
+ 'mocha': () => require('../mocha'),
44
+ 'mocha-each': () => require('../mocha'),
45
+ 'moleculer': () => require('../moleculer'),
46
+ 'mongodb': () => require('../mongodb-core'),
47
+ 'mongodb-core': () => require('../mongodb-core'),
48
+ 'mongoose': () => require('../mongoose'),
49
+ 'mysql': () => require('../mysql'),
50
+ 'mysql2': () => require('../mysql2'),
51
+ 'net': () => require('../net'),
52
+ 'next': () => require('../next'),
53
+ 'oracledb': () => require('../oracledb'),
54
+ 'paperplane': () => require('../paperplane'),
55
+ 'pg': () => require('../pg'),
56
+ 'pino': () => require('../pino'),
57
+ 'pino-pretty': () => require('../pino'),
58
+ 'promise-js': () => require('../promise-js'),
59
+ 'promise': () => require('../promise'),
60
+ 'q': () => require('../q'),
61
+ 'redis': () => require('../redis'),
62
+ 'restify': () => require('../restify'),
63
+ 'rhea': () => require('../rhea'),
64
+ 'router': () => require('../router'),
65
+ 'sharedb': () => require('../sharedb'),
66
+ 'tedious': () => require('../tedious'),
67
+ 'when': () => require('../when'),
68
+ 'winston': () => require('../winston')
69
+ }
@@ -1,16 +1,12 @@
1
1
  'use strict'
2
2
 
3
3
  const dc = require('diagnostics_channel')
4
- const path = require('path')
5
4
  const semver = require('semver')
6
- const Hook = require('./hook')
7
- const requirePackageJson = require('../../../dd-trace/src/require-package-json')
5
+ const instrumentations = require('./instrumentations')
8
6
  const { AsyncResource } = require('async_hooks')
9
- const log = require('../../../dd-trace/src/log')
10
7
 
11
- const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
12
8
  const channelMap = {}
13
- exports.channel = function channel (name) {
9
+ exports.channel = function (name) {
14
10
  const maybe = channelMap[name]
15
11
  if (maybe) return maybe
16
12
  const ch = dc.channel(name)
@@ -19,36 +15,11 @@ exports.channel = function channel (name) {
19
15
  }
20
16
 
21
17
  exports.addHook = function addHook ({ name, versions, file }, hook) {
22
- const fullFilename = filename(name, file)
23
-
24
- Hook([name], (moduleExports, moduleName, moduleBaseDir) => {
25
- moduleName = moduleName.replace(pathSepExpr, '/')
26
-
27
- if (moduleName !== fullFilename || !matchVersion(getVersion(moduleBaseDir), versions)) {
28
- return moduleExports
29
- }
30
-
31
- try {
32
- return hook(moduleExports)
33
- } catch (e) {
34
- log.error(e)
35
- return moduleExports
36
- }
37
- })
38
- }
39
-
40
- function matchVersion (version, ranges) {
41
- return !version || (ranges && ranges.some(range => semver.satisfies(semver.coerce(version), range)))
42
- }
43
-
44
- function getVersion (moduleBaseDir) {
45
- if (moduleBaseDir) {
46
- return requirePackageJson(moduleBaseDir, module).version
18
+ if (!instrumentations[name]) {
19
+ instrumentations[name] = []
47
20
  }
48
- }
49
21
 
50
- function filename (name, file) {
51
- return [name, file].filter(val => val).join('/')
22
+ instrumentations[name].push({ name, versions, file, hook })
52
23
  }
53
24
 
54
25
  // AsyncResource.bind exists and binds `this` properly only from 17.8.0 and up.
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const sym = Symbol.for('_ddtrace_instrumentations')
4
+
5
+ global[sym] = global[sym] || {}
6
+
7
+ module.exports = global[sym]
@@ -0,0 +1,59 @@
1
+ 'use strict'
2
+
3
+ const { channel } = require('diagnostics_channel')
4
+ const path = require('path')
5
+ const semver = require('semver')
6
+ const Hook = require('./hook')
7
+ const requirePackageJson = require('../../../dd-trace/src/require-package-json')
8
+ const log = require('../../../dd-trace/src/log')
9
+
10
+ const hooks = require('./hooks')
11
+ const instrumentations = require('./instrumentations')
12
+ const names = Object.keys(hooks)
13
+ const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
14
+
15
+ const loadChannel = channel('dd-trace:instrumentation:load')
16
+
17
+ // TODO: make this more efficient
18
+
19
+ for (const packageName of names) {
20
+ Hook([packageName], (moduleExports, moduleName, moduleBaseDir) => {
21
+ moduleName = moduleName.replace(pathSepExpr, '/')
22
+
23
+ hooks[packageName]()
24
+
25
+ for (const { name, file, versions, hook } of instrumentations[packageName]) {
26
+ const fullFilename = filename(name, file)
27
+
28
+ if (moduleName === fullFilename) {
29
+ const version = getVersion(moduleBaseDir)
30
+
31
+ if (matchVersion(version, versions)) {
32
+ try {
33
+ loadChannel.publish({ name, version, file })
34
+
35
+ moduleExports = hook(moduleExports)
36
+ } catch (e) {
37
+ log.error(e)
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ return moduleExports
44
+ })
45
+ }
46
+
47
+ function matchVersion (version, ranges) {
48
+ return !version || (ranges && ranges.some(range => semver.satisfies(semver.coerce(version), range)))
49
+ }
50
+
51
+ function getVersion (moduleBaseDir) {
52
+ if (moduleBaseDir) {
53
+ return requirePackageJson(moduleBaseDir, module).version
54
+ }
55
+ }
56
+
57
+ function filename (name, file) {
58
+ return [name, file].filter(val => val).join('/')
59
+ }
@@ -1,5 +1,5 @@
1
1
  'use strict'
2
-
2
+ const istanbul = require('istanbul-lib-coverage')
3
3
  const { addHook, channel, AsyncResource } = require('./helpers/instrument')
4
4
  const shimmer = require('../../datadog-shimmer')
5
5
 
@@ -7,7 +7,8 @@ const testStartCh = channel('ci:jest:test:start')
7
7
  const testSkippedCh = channel('ci:jest:test:skip')
8
8
  const testRunFinishCh = channel('ci:jest:test:finish')
9
9
  const testErrCh = channel('ci:jest:test:err')
10
- const testSuiteFinish = channel('ci:jest:test-suite:finish')
10
+
11
+ const testCodeCoverageCh = channel('ci:jest:test:code-coverage')
11
12
 
12
13
  const {
13
14
  getTestSuitePath,
@@ -16,6 +17,24 @@ const {
16
17
 
17
18
  const { getFormattedJestTestParameters, getJestTestName } = require('../../datadog-plugin-jest/src/util')
18
19
 
20
+ // This function also resets the coverage counters
21
+ function extractCoverageInformation (coverage, rootDir) {
22
+ const coverageMap = istanbul.createCoverageMap(coverage)
23
+
24
+ return coverageMap
25
+ .files()
26
+ .filter(filename => {
27
+ const fileCoverage = coverageMap.fileCoverageFor(filename)
28
+ const lineCoverage = fileCoverage.getLineCoverage()
29
+ const isAnyLineExecuted = Object.entries(lineCoverage).some(([, numExecutions]) => !!numExecutions)
30
+
31
+ fileCoverage.resetHits()
32
+
33
+ return isAnyLineExecuted
34
+ })
35
+ .map(filename => filename.replace(`${rootDir}/`, ''))
36
+ }
37
+
19
38
  const specStatusToTestStatus = {
20
39
  'pending': 'skip',
21
40
  'disabled': 'skip',
@@ -49,15 +68,11 @@ function getWrappedEnvironment (BaseEnvironment) {
49
68
  constructor (config, context) {
50
69
  super(config, context)
51
70
  const rootDir = config.globalConfig ? config.globalConfig.rootDir : config.rootDir
71
+ this.rootDir = rootDir
52
72
  this.testSuite = getTestSuitePath(context.testPath, rootDir)
53
73
  this.nameToParams = {}
54
74
  this.global._ddtrace = global._ddtrace
55
75
  }
56
- async teardown () {
57
- super.teardown().finally(() => {
58
- testSuiteFinish.publish()
59
- })
60
- }
61
76
 
62
77
  async handleTestEvent (event, state) {
63
78
  if (super.handleTestEvent) {
@@ -99,6 +114,10 @@ function getWrappedEnvironment (BaseEnvironment) {
99
114
  if (event.name === 'test_done') {
100
115
  const asyncResource = asyncResources.get(event.test)
101
116
  asyncResource.runInAsyncScope(() => {
117
+ if (this.global.__coverage__) {
118
+ const coverageFiles = extractCoverageInformation(this.global.__coverage__, this.rootDir)
119
+ testCodeCoverageCh.publish(coverageFiles)
120
+ }
102
121
  let status = 'pass'
103
122
  if (event.test.errors && event.test.errors.length) {
104
123
  status = 'fail'
@@ -111,10 +130,13 @@ function getWrappedEnvironment (BaseEnvironment) {
111
130
  })
112
131
  }
113
132
  if (event.name === 'test_skip' || event.name === 'test_todo') {
114
- testSkippedCh.publish({
115
- name: getJestTestName(event.test),
116
- suite: this.testSuite,
117
- runner: 'jest-circus'
133
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
134
+ asyncResource.runInAsyncScope(() => {
135
+ testSkippedCh.publish({
136
+ name: getJestTestName(event.test),
137
+ suite: this.testSuite,
138
+ runner: 'jest-circus'
139
+ })
118
140
  })
119
141
  }
120
142
  }
@@ -145,7 +145,7 @@ function wrapNext (req, next) {
145
145
  return function () {
146
146
  nextChannel.publish({ req })
147
147
 
148
- return next.apply(null, arguments)
148
+ return next.apply(this, arguments)
149
149
  }
150
150
  }
151
151
 
@@ -153,7 +153,10 @@ function mochaHook (Runner) {
153
153
  if (isHook && testOrHook.ctx) {
154
154
  test = testOrHook.ctx.currentTest
155
155
  }
156
- const asyncResource = getTestAsyncResource(test)
156
+ let asyncResource
157
+ if (test) {
158
+ asyncResource = getTestAsyncResource(test)
159
+ }
157
160
  if (asyncResource) {
158
161
  asyncResource.runInAsyncScope(() => {
159
162
  if (isHook) {
@@ -6,7 +6,10 @@ const handlers = ['use', 'pre']
6
6
  const methods = ['del', 'get', 'head', 'opts', 'post', 'put', 'patch']
7
7
 
8
8
  const handleChannel = channel('apm:restify:request:handle')
9
- const routeChannel = channel('apm:restify:request:route')
9
+ const errorChannel = channel('apm:restify:middleware:error')
10
+ const enterChannel = channel('apm:restify:middleware:enter')
11
+ const exitChannel = channel('apm:restify:middleware:exit')
12
+ const nextChannel = channel('apm:restify:middleware:next')
10
13
 
11
14
  function wrapSetupRequest (setupRequest) {
12
15
  return function (req, res) {
@@ -37,18 +40,37 @@ function wrapFn (fn) {
37
40
  if (Array.isArray(fn)) return wrapMiddleware(fn)
38
41
 
39
42
  return function (req, res, next) {
40
- if (req.route) {
41
- routeChannel.publish({ req, route: req.route })
43
+ if (typeof next === 'function') {
44
+ arguments[2] = wrapNext(req, next)
42
45
  }
43
46
 
44
- return fn.apply(this, arguments)
47
+ const route = req.route && req.route.path
48
+
49
+ enterChannel.publish({ req, route })
50
+
51
+ try {
52
+ return fn.apply(this, arguments)
53
+ } catch (error) {
54
+ errorChannel.publish({ req, error })
55
+ nextChannel.publish({ req })
56
+ exitChannel.publish({ req })
57
+ }
58
+ }
59
+ }
60
+
61
+ function wrapNext (req, next) {
62
+ return function () {
63
+ nextChannel.publish({ req })
64
+ exitChannel.publish({ req })
65
+
66
+ next.apply(this, arguments)
45
67
  }
46
68
  }
47
69
 
48
70
  addHook({ name: 'restify', versions: ['>=3'], file: 'lib/server.js' }, Server => {
49
71
  shimmer.wrap(Server.prototype, '_setupRequest', wrapSetupRequest)
50
72
  shimmer.massWrap(Server.prototype, handlers, wrapHandler)
51
- shimmer.wrap(Server.prototype, methods, wrapMethod)
73
+ shimmer.massWrap(Server.prototype, methods, wrapMethod)
52
74
 
53
75
  return Server
54
76
  })
@@ -97,7 +97,7 @@ function createWrapRouterMethod (name) {
97
97
  nextChannel.publish({ req })
98
98
  exitChannel.publish({ req })
99
99
 
100
- next.apply(null, arguments)
100
+ next.apply(this, arguments)
101
101
  }
102
102
  }
103
103
 
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const Tags = require('opentracing').Tags
4
3
  const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
5
4
  const Plugin = require('../../dd-trace/src/plugins/plugin')
6
5
  const { storage } = require('../../datadog-core')
@@ -33,7 +32,7 @@ class BaseAwsSdkPlugin extends Plugin {
33
32
  const serviceName = this.getServiceName(serviceIdentifier)
34
33
  const childOf = this.tracer.scope().active()
35
34
  const tags = {
36
- [Tags.SPAN_KIND]: 'client',
35
+ 'span.kind': 'client',
37
36
  'service.name': serviceName,
38
37
  'aws.operation': operation,
39
38
  'aws.region': awsRegion,
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const Tags = require('opentracing').Tags
4
3
  const log = require('../../../dd-trace/src/log')
5
4
  const BaseAwsSdkPlugin = require('../base')
6
5
  const { storage } = require('../../../datadog-core')
@@ -25,7 +24,7 @@ class Sqs extends BaseAwsSdkPlugin {
25
24
  tags: Object.assign(
26
25
  {},
27
26
  this.requestTags.get(request) || {},
28
- { [Tags.SPAN_KIND]: 'server' }
27
+ { 'span.kind': 'server' }
29
28
  )
30
29
  }
31
30
  const span = plugin.tracer.startSpan('aws.response', options)
@@ -30,6 +30,10 @@ class CucumberPlugin extends Plugin {
30
30
  const sourceRoot = process.cwd()
31
31
  const codeOwnersEntries = getCodeOwnersFileEntries(sourceRoot)
32
32
 
33
+ this.addSub('ci:cucumber:session:finish', () => {
34
+ this.tracer._exporter._writer.flush()
35
+ })
36
+
33
37
  this.addSub('ci:cucumber:run:start', ({ pickleName, pickleUri }) => {
34
38
  const store = storage.getStore()
35
39
  const childOf = store ? store.span : store