dd-trace 2.4.2 → 2.7.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.
- package/LICENSE-3rdparty.csv +1 -2
- package/ci/init.js +6 -0
- package/ci/jest/env.js +16 -3
- package/ext/exporters.d.ts +2 -1
- package/ext/exporters.js +2 -1
- package/index.d.ts +17 -8
- package/package.json +20 -23
- package/packages/datadog-instrumentations/index.js +14 -0
- package/packages/datadog-instrumentations/src/connect.js +111 -0
- package/packages/datadog-instrumentations/src/cypress.js +8 -0
- package/packages/datadog-instrumentations/src/express.js +27 -0
- package/packages/datadog-instrumentations/src/fastify.js +187 -0
- package/packages/datadog-instrumentations/src/find-my-way.js +30 -0
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -0
- package/packages/datadog-instrumentations/src/http/server.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +175 -0
- package/packages/datadog-instrumentations/src/kafkajs.js +112 -0
- package/packages/datadog-instrumentations/src/knex.js +20 -0
- package/packages/datadog-instrumentations/src/koa.js +159 -0
- package/packages/datadog-instrumentations/src/limitd-client.js +21 -0
- package/packages/datadog-instrumentations/src/oracledb.js +128 -0
- package/packages/datadog-instrumentations/src/paperplane.js +77 -0
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/restify.js +58 -0
- package/packages/datadog-instrumentations/src/rhea.js +1 -1
- package/packages/datadog-instrumentations/src/router.js +177 -0
- package/packages/datadog-plugin-aws-sdk/src/helpers.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
- package/packages/datadog-plugin-connect/src/index.js +10 -114
- package/packages/datadog-plugin-cucumber/src/index.js +16 -16
- package/packages/datadog-plugin-cypress/src/index.js +10 -5
- package/packages/datadog-plugin-cypress/src/plugin.js +18 -17
- package/packages/datadog-plugin-dns/src/index.js +12 -1
- package/packages/datadog-plugin-express/src/index.js +11 -25
- package/packages/datadog-plugin-fastify/src/index.js +17 -4
- package/packages/datadog-plugin-find-my-way/src/index.js +20 -0
- package/packages/datadog-plugin-fs/src/index.js +2 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +56 -111
- package/packages/datadog-plugin-http/src/server.js +2 -10
- package/packages/datadog-plugin-jest/src/index.js +101 -3
- package/packages/datadog-plugin-jest/src/util.js +1 -29
- package/packages/datadog-plugin-kafkajs/src/index.js +64 -90
- package/packages/datadog-plugin-koa/src/index.js +12 -164
- package/packages/datadog-plugin-mocha/src/index.js +14 -15
- package/packages/datadog-plugin-oracledb/src/index.js +34 -100
- package/packages/datadog-plugin-paperplane/src/index.js +14 -100
- package/packages/datadog-plugin-paperplane/src/logger.js +11 -0
- package/packages/datadog-plugin-paperplane/src/server.js +24 -0
- package/packages/datadog-plugin-restify/src/index.js +13 -75
- package/packages/datadog-plugin-router/src/index.js +67 -164
- package/packages/datadog-plugin-web/src/index.js +20 -0
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +34 -12
- package/packages/dd-trace/src/appsec/index.js +7 -3
- package/packages/dd-trace/src/appsec/recommended.json +15 -5
- package/packages/dd-trace/src/appsec/reporter.js +33 -3
- package/packages/dd-trace/src/appsec/rule_manager.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +32 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +51 -0
- package/packages/dd-trace/src/config.js +33 -4
- package/packages/dd-trace/src/encode/0.4.js +0 -1
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +193 -0
- package/packages/dd-trace/src/encode/tags-processors.js +116 -0
- package/packages/dd-trace/src/exporter.js +3 -0
- package/packages/dd-trace/src/exporters/agent/index.js +1 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -32
- package/packages/dd-trace/src/exporters/{agent → common}/docker.js +0 -0
- package/packages/dd-trace/src/exporters/common/request.js +83 -0
- package/packages/dd-trace/src/exporters/common/writer.js +36 -0
- package/packages/dd-trace/src/exporters/{agent/scheduler.js → scheduler.js} +0 -0
- package/packages/dd-trace/src/format.js +9 -5
- package/packages/dd-trace/src/instrumenter.js +3 -0
- package/packages/dd-trace/src/pkg.js +11 -6
- package/packages/dd-trace/src/plugin_manager.js +13 -7
- package/packages/dd-trace/src/plugins/index.js +1 -2
- package/packages/dd-trace/src/plugins/log_plugin.js +8 -4
- package/packages/dd-trace/src/plugins/plugin.js +8 -0
- package/packages/dd-trace/src/plugins/util/test.js +79 -1
- package/packages/dd-trace/src/plugins/util/web.js +41 -12
- package/packages/dd-trace/src/profiling/config.js +8 -8
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/index.js +4 -4
- package/packages/dd-trace/src/profiling/profilers/{heap.js → space.js} +2 -2
- package/packages/dd-trace/src/profiling/profilers/{cpu.js → wall.js} +3 -3
- package/packages/dd-trace/src/proxy.js +2 -0
- package/packages/dd-trace/src/span_processor.js +4 -1
- package/packages/dd-trace/src/telemetry.js +187 -0
- package/scripts/install_plugin_modules.js +1 -0
- package/packages/datadog-plugin-fastify/src/fastify.js +0 -198
- package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -37
- package/packages/datadog-plugin-jest/src/jest-environment.js +0 -272
- package/packages/datadog-plugin-jest/src/jest-jasmine2.js +0 -185
- package/packages/datadog-plugin-knex/src/index.js +0 -23
- package/packages/datadog-plugin-limitd-client/src/index.js +0 -30
- package/packages/dd-trace/src/exporters/agent/request.js +0 -86
- package/scripts/postpublish.js +0 -24
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
const connectionAttributes = new WeakMap()
|
|
11
|
+
const poolAttributes = new WeakMap()
|
|
12
|
+
|
|
13
|
+
const executeStartChannel = channel('apm:oracledb:execute:start')
|
|
14
|
+
const executeErrorChannel = channel('apm:oracledb:execute:error')
|
|
15
|
+
const executeFinishChannel = channel('apm:oracledb:execute:finish')
|
|
16
|
+
|
|
17
|
+
function finish (err) {
|
|
18
|
+
if (err) {
|
|
19
|
+
executeErrorChannel.publish(err)
|
|
20
|
+
}
|
|
21
|
+
executeFinishChannel.publish(undefined)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
addHook({ name: 'oracledb', versions: ['5'] }, oracledb => {
|
|
25
|
+
shimmer.wrap(oracledb.Connection.prototype, 'execute', execute => {
|
|
26
|
+
return function wrappedExecute (dbQuery, ...args) {
|
|
27
|
+
if (!executeStartChannel.hasSubscribers) {
|
|
28
|
+
return execute.apply(this, arguments)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (arguments.length && typeof arguments[arguments.length - 1] === 'function') {
|
|
32
|
+
const cb = arguments[arguments.length - 1]
|
|
33
|
+
const outerAr = new AsyncResource('apm:oracledb:outer-scope')
|
|
34
|
+
arguments[arguments.length - 1] = function wrappedCb (err, result) {
|
|
35
|
+
finish(err)
|
|
36
|
+
return outerAr.runInAsyncScope(() => cb.apply(this, arguments))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return new AsyncResource('apm:oracledb:inner-scope').runInAsyncScope(() => {
|
|
41
|
+
const connAttrs = connectionAttributes.get(this)
|
|
42
|
+
executeStartChannel.publish({ query: dbQuery, connAttrs })
|
|
43
|
+
try {
|
|
44
|
+
let result = execute.apply(this, arguments)
|
|
45
|
+
|
|
46
|
+
if (result && typeof result.then === 'function') {
|
|
47
|
+
result = result.then(
|
|
48
|
+
x => {
|
|
49
|
+
finish()
|
|
50
|
+
return x
|
|
51
|
+
},
|
|
52
|
+
e => {
|
|
53
|
+
finish(e)
|
|
54
|
+
throw e
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result
|
|
60
|
+
} catch (err) {
|
|
61
|
+
executeErrorChannel.publish(err)
|
|
62
|
+
throw err
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
shimmer.wrap(oracledb, 'getConnection', getConnection => {
|
|
68
|
+
return function wrappedGetConnection (connAttrs, callback) {
|
|
69
|
+
if (callback) {
|
|
70
|
+
arguments[1] = (err, connection) => {
|
|
71
|
+
if (connection) {
|
|
72
|
+
connectionAttributes.set(connection, connAttrs)
|
|
73
|
+
}
|
|
74
|
+
callback(err, connection)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getConnection.apply(this, arguments)
|
|
78
|
+
} else {
|
|
79
|
+
return getConnection.apply(this, arguments).then((connection) => {
|
|
80
|
+
connectionAttributes.set(connection, connAttrs)
|
|
81
|
+
return connection
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
shimmer.wrap(oracledb, 'createPool', createPool => {
|
|
87
|
+
return function wrappedCreatePool (poolAttrs, callback) {
|
|
88
|
+
if (callback) {
|
|
89
|
+
arguments[1] = (err, pool) => {
|
|
90
|
+
if (pool) {
|
|
91
|
+
poolAttributes.set(pool, poolAttrs)
|
|
92
|
+
}
|
|
93
|
+
callback(err, pool)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
createPool.apply(this, arguments)
|
|
97
|
+
} else {
|
|
98
|
+
return createPool.apply(this, arguments).then((pool) => {
|
|
99
|
+
poolAttributes.set(pool, poolAttrs)
|
|
100
|
+
return pool
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
shimmer.wrap(oracledb.Pool.prototype, 'getConnection', getConnection => {
|
|
106
|
+
return function wrappedGetConnection () {
|
|
107
|
+
let callback
|
|
108
|
+
if (typeof arguments[arguments.length - 1] === 'function') {
|
|
109
|
+
callback = arguments[arguments.length - 1]
|
|
110
|
+
}
|
|
111
|
+
if (callback) {
|
|
112
|
+
arguments[arguments.length - 1] = (err, connection) => {
|
|
113
|
+
if (connection) {
|
|
114
|
+
connectionAttributes.set(connection, poolAttributes.get(this))
|
|
115
|
+
}
|
|
116
|
+
callback(err, connection)
|
|
117
|
+
}
|
|
118
|
+
getConnection.apply(this, arguments)
|
|
119
|
+
} else {
|
|
120
|
+
return getConnection.apply(this, arguments).then((connection) => {
|
|
121
|
+
connectionAttributes.set(connection, poolAttributes.get(this))
|
|
122
|
+
return connection
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
return oracledb
|
|
128
|
+
})
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { addHook, channel } = require('./helpers/instrument')
|
|
4
|
+
const shimmer = require('../../datadog-shimmer')
|
|
5
|
+
|
|
6
|
+
const logChannel = channel('apm:paperplane:log')
|
|
7
|
+
const handleChannel = channel('apm:paperplane:request:handle')
|
|
8
|
+
const routeChannel = channel('apm:paperplane:request:route')
|
|
9
|
+
|
|
10
|
+
const nodeMajor = Number(process.versions.node.split('.')[0])
|
|
11
|
+
const name = 'paperplane'
|
|
12
|
+
const versions = nodeMajor <= 12 ? ['>=2.3.2'] : nodeMajor <= 14 ? ['>=3.1.1'] : []
|
|
13
|
+
|
|
14
|
+
const wrapRoute = handler => req => {
|
|
15
|
+
const { original, route } = req
|
|
16
|
+
|
|
17
|
+
if (routeChannel.hasSubscribers) {
|
|
18
|
+
routeChannel.publish({ req: original, route })
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return handler(req)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const wrapLogger = logger => record => {
|
|
25
|
+
const event = { message: record }
|
|
26
|
+
|
|
27
|
+
logChannel.publish(event)
|
|
28
|
+
|
|
29
|
+
return logger(event.message)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const wrapMount = mount => opts => {
|
|
33
|
+
const handler = mount(opts)
|
|
34
|
+
|
|
35
|
+
return function (req, res) {
|
|
36
|
+
handleChannel.publish(req)
|
|
37
|
+
|
|
38
|
+
return handler.apply(this, arguments)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const wrapRoutes = routes => handlers => {
|
|
43
|
+
const traced = {}
|
|
44
|
+
|
|
45
|
+
for (const route in handlers) {
|
|
46
|
+
traced[route] = wrapRoute(handlers[route])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return routes(traced)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
addHook({ name, versions, file: 'lib/logger.js' }, exports => {
|
|
53
|
+
shimmer.wrap(exports, 'logger', wrapLogger)
|
|
54
|
+
|
|
55
|
+
return exports
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
addHook({ name, versions, file: 'lib/mount.js' }, exports => {
|
|
59
|
+
shimmer.wrap(exports, 'mount', wrapMount)
|
|
60
|
+
|
|
61
|
+
return exports
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
addHook({ name, versions, file: 'lib/routes.js' }, exports => {
|
|
65
|
+
shimmer.wrap(exports, 'routes', wrapRoutes)
|
|
66
|
+
|
|
67
|
+
return exports
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
if (nodeMajor <= 12) {
|
|
71
|
+
addHook({ name, versions: ['2.3.0 - 2.3.1'] }, paperplane => {
|
|
72
|
+
shimmer.wrap(paperplane, 'mount', wrapMount)
|
|
73
|
+
shimmer.wrap(paperplane, 'routes', wrapRoutes)
|
|
74
|
+
|
|
75
|
+
return paperplane
|
|
76
|
+
})
|
|
77
|
+
}
|
|
@@ -12,12 +12,12 @@ const asyncEndCh = channel('apm:pg:query:async-end')
|
|
|
12
12
|
const endCh = channel('apm:pg:query:end')
|
|
13
13
|
const errorCh = channel('apm:pg:query:error')
|
|
14
14
|
|
|
15
|
-
addHook({ name: 'pg', versions: ['>=4'] }, pg => {
|
|
15
|
+
addHook({ name: 'pg', versions: ['>=4.5.5'] }, pg => {
|
|
16
16
|
shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
|
|
17
17
|
return pg
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=4'] }, Client => {
|
|
20
|
+
addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=4.5.5'] }, Client => {
|
|
21
21
|
shimmer.wrap(Client.prototype, 'query', query => wrapQuery(query))
|
|
22
22
|
return Client
|
|
23
23
|
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
5
|
+
const handlers = ['use', 'pre']
|
|
6
|
+
const methods = ['del', 'get', 'head', 'opts', 'post', 'put', 'patch']
|
|
7
|
+
|
|
8
|
+
const handleChannel = channel('apm:restify:request:handle')
|
|
9
|
+
const routeChannel = channel('apm:restify:request:route')
|
|
10
|
+
|
|
11
|
+
function wrapSetupRequest (setupRequest) {
|
|
12
|
+
return function setupRequestWithTrace (req, res) {
|
|
13
|
+
handleChannel.publish({ req, res })
|
|
14
|
+
return setupRequest.apply(this, arguments)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function wrapMethod (method) {
|
|
19
|
+
return function methodWithTrace (path) {
|
|
20
|
+
const middleware = wrapMiddleware(Array.prototype.slice.call(arguments, 1))
|
|
21
|
+
|
|
22
|
+
return method.apply(this, [path].concat(middleware))
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function wrapHandler (method) {
|
|
27
|
+
return function methodWithTrace () {
|
|
28
|
+
return method.apply(this, wrapMiddleware(arguments))
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function wrapMiddleware (middleware) {
|
|
33
|
+
return Array.prototype.map.call(middleware, wrapFn)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function wrapFn (fn) {
|
|
37
|
+
if (Array.isArray(fn)) return wrapMiddleware(fn)
|
|
38
|
+
|
|
39
|
+
return function (req, res, next) {
|
|
40
|
+
if (typeof next === 'function') {
|
|
41
|
+
arguments[2] = AsyncResource.bind(next)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (req.route) {
|
|
45
|
+
routeChannel.publish({ req, route: req.route })
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return fn.apply(this, arguments)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
addHook({ name: 'restify', versions: ['>=3'], file: 'lib/server.js' }, Server => {
|
|
53
|
+
shimmer.wrap(Server.prototype, '_setupRequest', wrapSetupRequest)
|
|
54
|
+
shimmer.massWrap(Server.prototype, handlers, wrapHandler)
|
|
55
|
+
shimmer.wrap(Server.prototype, methods, wrapMethod)
|
|
56
|
+
|
|
57
|
+
return Server
|
|
58
|
+
})
|
|
@@ -147,7 +147,7 @@ function wrapDeliveryUpdate (obj, update) {
|
|
|
147
147
|
function patchCircularBuffer (proto, Session) {
|
|
148
148
|
Object.defineProperty(proto, 'outgoing', {
|
|
149
149
|
configurable: true,
|
|
150
|
-
get () {},
|
|
150
|
+
get () { return undefined },
|
|
151
151
|
set (outgoing) {
|
|
152
152
|
delete proto.outgoing // removes the setter on the prototype
|
|
153
153
|
this.outgoing = outgoing // assigns on the instance, like normal
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const METHODS = require('methods').concat('all')
|
|
4
|
+
const pathToRegExp = require('path-to-regexp')
|
|
5
|
+
const shimmer = require('../../datadog-shimmer')
|
|
6
|
+
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
7
|
+
|
|
8
|
+
function createWrapRouterMethod (name) {
|
|
9
|
+
const enterChannel = channel(`apm:${name}:middleware:enter`)
|
|
10
|
+
const errorChannel = channel(`apm:${name}:middleware:error`)
|
|
11
|
+
const exitChannel = channel(`apm:${name}:middleware:exit`)
|
|
12
|
+
|
|
13
|
+
const layerMatchers = new WeakMap()
|
|
14
|
+
const regexpCache = Object.create(null)
|
|
15
|
+
|
|
16
|
+
function wrapLayerHandle (layer, original) {
|
|
17
|
+
original._name = original._name || layer.name
|
|
18
|
+
|
|
19
|
+
const handle = shimmer.wrap(original, function () {
|
|
20
|
+
if (!enterChannel.hasSubscribers) return original.apply(this, arguments)
|
|
21
|
+
|
|
22
|
+
const matchers = layerMatchers.get(layer)
|
|
23
|
+
const middlewareResource = new AsyncResource('bound-anonymous-fn')
|
|
24
|
+
const lastIndex = arguments.length - 1
|
|
25
|
+
const name = original._name || original.name
|
|
26
|
+
const req = arguments[arguments.length > 3 ? 1 : 0]
|
|
27
|
+
const next = AsyncResource.bind(arguments[lastIndex])
|
|
28
|
+
|
|
29
|
+
if (typeof next === 'function') {
|
|
30
|
+
arguments[lastIndex] = wrapNext(req, middlewareResource.bind(next))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return middlewareResource.runInAsyncScope(() => {
|
|
34
|
+
let route
|
|
35
|
+
|
|
36
|
+
if (matchers) {
|
|
37
|
+
// Try to guess which path actually matched
|
|
38
|
+
for (let i = 0; i < matchers.length; i++) {
|
|
39
|
+
if (matchers[i].test(layer)) {
|
|
40
|
+
route = matchers[i].path
|
|
41
|
+
|
|
42
|
+
break
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
enterChannel.publish({ name, req, route })
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
return original.apply(this, arguments)
|
|
51
|
+
} catch (e) {
|
|
52
|
+
errorChannel.publish(e)
|
|
53
|
+
exitChannel.publish({ req })
|
|
54
|
+
|
|
55
|
+
throw e
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// This is a workaround for the `loopback` library so that it can find the correct express layer
|
|
61
|
+
// that contains the real handle function
|
|
62
|
+
handle._datadog_orig = original
|
|
63
|
+
|
|
64
|
+
return handle
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function wrapStack (stack, offset, matchers) {
|
|
68
|
+
[].concat(stack).slice(offset).forEach(layer => {
|
|
69
|
+
if (layer.__handle) { // express-async-errors
|
|
70
|
+
layer.__handle = wrapLayerHandle(layer, layer.__handle)
|
|
71
|
+
} else {
|
|
72
|
+
layer.handle = wrapLayerHandle(layer, layer.handle)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
layerMatchers.set(layer, matchers)
|
|
76
|
+
|
|
77
|
+
if (layer.route) {
|
|
78
|
+
METHODS.forEach(method => {
|
|
79
|
+
if (typeof layer.route.stack === 'function') {
|
|
80
|
+
layer.route.stack = [{ handle: layer.route.stack }]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
layer.route[method] = wrapMethod(layer.route[method])
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function wrapNext (req, next) {
|
|
90
|
+
return function (error) {
|
|
91
|
+
if (error) {
|
|
92
|
+
errorChannel.publish(error)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
exitChannel.publish({ req })
|
|
96
|
+
|
|
97
|
+
next.apply(null, arguments)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function extractMatchers (fn) {
|
|
102
|
+
const arg = flatten([].concat(fn))
|
|
103
|
+
|
|
104
|
+
if (typeof arg[0] === 'function') {
|
|
105
|
+
return []
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return arg.map(pattern => ({
|
|
109
|
+
path: pattern instanceof RegExp ? `(${pattern})` : pattern,
|
|
110
|
+
test: layer => {
|
|
111
|
+
const matchers = layerMatchers.get(layer)
|
|
112
|
+
|
|
113
|
+
return !isFastStar(layer, matchers) &&
|
|
114
|
+
!isFastSlash(layer, matchers) &&
|
|
115
|
+
cachedPathToRegExp(pattern).test(layer.path)
|
|
116
|
+
}
|
|
117
|
+
}))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function isFastStar (layer, matchers) {
|
|
121
|
+
if (layer.regexp.fast_star !== undefined) {
|
|
122
|
+
return layer.regexp.fast_star
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return matchers.some(matcher => matcher.path === '*')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function isFastSlash (layer, matchers) {
|
|
129
|
+
if (layer.regexp.fast_slash !== undefined) {
|
|
130
|
+
return layer.regexp.fast_slash
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return matchers.some(matcher => matcher.path === '/')
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function flatten (arr) {
|
|
137
|
+
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), [])
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function cachedPathToRegExp (pattern) {
|
|
141
|
+
const maybeCached = regexpCache[pattern]
|
|
142
|
+
if (maybeCached) {
|
|
143
|
+
return maybeCached
|
|
144
|
+
}
|
|
145
|
+
const regexp = pathToRegExp(pattern)
|
|
146
|
+
regexpCache[pattern] = regexp
|
|
147
|
+
return regexp
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function wrapMethod (original) {
|
|
151
|
+
return function methodWithTrace (fn) {
|
|
152
|
+
const offset = this.stack ? [].concat(this.stack).length : 0
|
|
153
|
+
const router = original.apply(this, arguments)
|
|
154
|
+
|
|
155
|
+
if (typeof this.stack === 'function') {
|
|
156
|
+
this.stack = [{ handle: this.stack }]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
wrapStack(this.stack, offset, extractMatchers(fn))
|
|
160
|
+
|
|
161
|
+
return router
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return wrapMethod
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const wrapRouterMethod = createWrapRouterMethod('router')
|
|
169
|
+
|
|
170
|
+
addHook({ name: 'router', versions: ['>=1'] }, Router => {
|
|
171
|
+
shimmer.wrap(Router.prototype, 'use', wrapRouterMethod)
|
|
172
|
+
shimmer.wrap(Router.prototype, 'route', wrapRouterMethod)
|
|
173
|
+
|
|
174
|
+
return Router
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
module.exports = { createWrapRouterMethod }
|
|
@@ -19,7 +19,7 @@ function getService (Service) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const helpers = {
|
|
22
|
-
finish (span, err) {
|
|
22
|
+
finish (config, span, response, err) {
|
|
23
23
|
if (err) {
|
|
24
24
|
span.setTag('error', err)
|
|
25
25
|
|
|
@@ -28,6 +28,8 @@ const helpers = {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
config.hooks.request(span, response)
|
|
32
|
+
|
|
31
33
|
span.finish()
|
|
32
34
|
},
|
|
33
35
|
|
|
@@ -43,14 +45,12 @@ const helpers = {
|
|
|
43
45
|
: true
|
|
44
46
|
},
|
|
45
47
|
|
|
46
|
-
addResponseTags (span, response, serviceName
|
|
48
|
+
addResponseTags (span, response, serviceName) {
|
|
47
49
|
if (!span) return
|
|
48
50
|
|
|
49
51
|
if (response.request) {
|
|
50
52
|
this.addServicesTags(span, response, serviceName)
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
config.hooks.request(span, response)
|
|
54
54
|
},
|
|
55
55
|
|
|
56
56
|
addServicesTags (span, response, serviceName) {
|
|
@@ -36,7 +36,7 @@ function createWrapRequest (tracer, config) {
|
|
|
36
36
|
if (!span) return
|
|
37
37
|
|
|
38
38
|
awsHelpers.addResponseTags(span, response, serviceIdentifier, config, tracer)
|
|
39
|
-
awsHelpers.finish(span, response.error)
|
|
39
|
+
awsHelpers.finish(config, span, response, response.error)
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
analyticsSampler.sample(span, config.measured)
|
|
@@ -1,123 +1,19 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const RouterPlugin = require('../../datadog-plugin-router/src')
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return function connectWithTrace () {
|
|
10
|
-
const app = connect()
|
|
11
|
-
|
|
12
|
-
if (!app) return app
|
|
13
|
-
|
|
14
|
-
app.use = createWrapUse()(app.use)
|
|
15
|
-
app.handle = createWrapHandle(tracer, config)(app.handle)
|
|
16
|
-
|
|
17
|
-
return app
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function createWrapUse () {
|
|
23
|
-
return function wrapUse (use) {
|
|
24
|
-
if (typeof use !== 'function') return use
|
|
25
|
-
|
|
26
|
-
return function useWithTrace (route, fn) {
|
|
27
|
-
const result = use.apply(this, arguments)
|
|
28
|
-
|
|
29
|
-
if (!this || !Array.isArray(this.stack)) return result
|
|
30
|
-
|
|
31
|
-
const index = this.stack.length - 1
|
|
32
|
-
const layer = this.stack[index]
|
|
33
|
-
|
|
34
|
-
if (layer && layer.handle) {
|
|
35
|
-
this.stack[index].handle = wrapLayerHandle(layer)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return result
|
|
39
|
-
}
|
|
5
|
+
class ConnectPlugin extends RouterPlugin {
|
|
6
|
+
static get name () {
|
|
7
|
+
return 'connect'
|
|
40
8
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function createWrapHandle (tracer, config) {
|
|
44
|
-
config = web.normalizeConfig(config)
|
|
45
9
|
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
constructor (...args) {
|
|
11
|
+
super(...args)
|
|
48
12
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})
|
|
53
|
-
}
|
|
13
|
+
this.addSub('apm:connect:request:handle', ({ req }) => {
|
|
14
|
+
this.setFramework(req, 'connect', this.config)
|
|
15
|
+
})
|
|
54
16
|
}
|
|
55
17
|
}
|
|
56
18
|
|
|
57
|
-
|
|
58
|
-
if (typeof layer.handle !== 'function') return layer.handle
|
|
59
|
-
|
|
60
|
-
const handle = layer.handle
|
|
61
|
-
|
|
62
|
-
if (layer.handle.length === 4) {
|
|
63
|
-
return function (error, req, res, next) {
|
|
64
|
-
return callLayerHandle(layer, handle, req, [error, req, res, wrapNext(layer, req, next)])
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
return function (req, res, next) {
|
|
68
|
-
return callLayerHandle(layer, handle, req, [req, res, wrapNext(layer, req, next)])
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function callLayerHandle (layer, handle, req, args) {
|
|
74
|
-
const route = layer.route
|
|
75
|
-
|
|
76
|
-
if (route !== '/') {
|
|
77
|
-
web.enterRoute(req, route)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return web.wrapMiddleware(req, handle, 'connect.middleware', () => {
|
|
81
|
-
return handle.apply(layer, args)
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function wrapNext (layer, req, next) {
|
|
86
|
-
if (typeof next !== 'function' || !web.active(req)) return next
|
|
87
|
-
|
|
88
|
-
return function nextWithTrace (error) {
|
|
89
|
-
if (!error && layer.route !== '/') {
|
|
90
|
-
web.exitRoute(req)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
web.finish(req, error)
|
|
94
|
-
|
|
95
|
-
next.apply(this, arguments)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
module.exports = [
|
|
100
|
-
{
|
|
101
|
-
name: 'connect',
|
|
102
|
-
versions: ['>=3'],
|
|
103
|
-
patch (connect, tracer, config) {
|
|
104
|
-
// `connect` is a function so we return a wrapper that will replace its export.
|
|
105
|
-
return this.wrapExport(connect, createWrapConnect(tracer, config)(connect))
|
|
106
|
-
},
|
|
107
|
-
unpatch (connect) {
|
|
108
|
-
this.unwrapExport(connect)
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: 'connect',
|
|
113
|
-
versions: ['2.2.2'],
|
|
114
|
-
patch (connect, tracer, config) {
|
|
115
|
-
this.wrap(connect.proto, 'use', createWrapUse())
|
|
116
|
-
this.wrap(connect.proto, 'handle', createWrapHandle(tracer, config))
|
|
117
|
-
},
|
|
118
|
-
unpatch (connect) {
|
|
119
|
-
this.unwrap(connect.proto, 'use')
|
|
120
|
-
this.unwrap(connect.proto, 'handle')
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
]
|
|
19
|
+
module.exports = ConnectPlugin
|