dd-trace 2.3.0 → 2.4.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.
- package/ci/init.js +26 -2
- package/index.d.ts +51 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/index.js +10 -0
- package/packages/datadog-instrumentations/src/amqp10.js +70 -0
- package/packages/datadog-instrumentations/src/amqplib.js +58 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +191 -0
- package/packages/datadog-instrumentations/src/cucumber.js +27 -12
- package/packages/datadog-instrumentations/src/helpers/hook.js +44 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +31 -58
- package/packages/datadog-instrumentations/src/http/client.js +170 -0
- package/packages/datadog-instrumentations/src/http/server.js +61 -0
- package/packages/datadog-instrumentations/src/http.js +4 -0
- package/packages/datadog-instrumentations/src/mocha.js +139 -0
- package/packages/datadog-instrumentations/src/mongodb-core.js +179 -0
- package/packages/datadog-instrumentations/src/net.js +117 -0
- package/packages/datadog-instrumentations/src/pg.js +75 -0
- package/packages/datadog-instrumentations/src/rhea.js +224 -0
- package/packages/datadog-instrumentations/src/tedious.js +66 -0
- package/packages/datadog-plugin-amqp10/src/index.js +79 -122
- package/packages/datadog-plugin-amqplib/src/index.js +77 -142
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -2
- package/packages/datadog-plugin-cassandra-driver/src/index.js +52 -224
- package/packages/datadog-plugin-cucumber/src/index.js +3 -1
- package/packages/datadog-plugin-http/src/client.js +111 -254
- package/packages/datadog-plugin-http/src/index.js +29 -3
- package/packages/datadog-plugin-http/src/server.js +49 -32
- package/packages/datadog-plugin-jest/src/jest-jasmine2.js +5 -3
- package/packages/datadog-plugin-mocha/src/index.js +96 -207
- package/packages/datadog-plugin-mongodb-core/src/index.js +119 -3
- package/packages/datadog-plugin-net/src/index.js +65 -121
- package/packages/datadog-plugin-next/src/index.js +10 -10
- package/packages/datadog-plugin-pg/src/index.js +32 -69
- package/packages/datadog-plugin-rhea/src/index.js +59 -225
- package/packages/datadog-plugin-tedious/src/index.js +38 -86
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/recommended.json +137 -116
- package/packages/dd-trace/src/config.js +6 -0
- package/packages/dd-trace/src/iitm.js +5 -1
- package/packages/dd-trace/src/loader.js +6 -4
- package/packages/dd-trace/src/noop/tracer.js +4 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +34 -1
- package/packages/dd-trace/src/opentracing/span.js +34 -0
- package/packages/dd-trace/src/plugin_manager.js +4 -0
- package/packages/dd-trace/src/plugins/plugin.js +3 -1
- package/packages/dd-trace/src/plugins/util/web.js +99 -93
- package/packages/dd-trace/src/proxy.js +4 -0
- package/packages/dd-trace/src/ritm.js +60 -25
- package/packages/dd-trace/src/tracer.js +16 -0
- package/packages/datadog-plugin-mongodb-core/src/legacy.js +0 -59
- package/packages/datadog-plugin-mongodb-core/src/unified.js +0 -138
- package/packages/datadog-plugin-mongodb-core/src/util.js +0 -143
package/ci/init.js
CHANGED
|
@@ -1,12 +1,36 @@
|
|
|
1
|
+
const path = require('path')
|
|
1
2
|
const tracer = require('../packages/dd-trace')
|
|
2
3
|
const { ORIGIN_KEY } = require('../packages/dd-trace/src/constants')
|
|
4
|
+
const { mochaHook } = require('../packages/datadog-instrumentations/src/mocha')
|
|
5
|
+
const { pickleHook, testCaseHook } = require('../packages/datadog-instrumentations/src/cucumber')
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
const options = {
|
|
5
8
|
startupLogs: false,
|
|
6
9
|
tags: {
|
|
7
10
|
[ORIGIN_KEY]: 'ciapp-test'
|
|
8
11
|
}
|
|
9
|
-
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// TODO: remove this in a later major version since we now recommend using
|
|
15
|
+
// `NODE_OPTIONS='-r dd-trace/ci/init'`.
|
|
16
|
+
try {
|
|
17
|
+
for (const filename in require.cache) {
|
|
18
|
+
const cache = require.cache[filename]
|
|
19
|
+
const id = filename.split(path.sep).join('/')
|
|
20
|
+
|
|
21
|
+
if (id.includes('/node_modules/mocha/lib/runner.js')) {
|
|
22
|
+
cache.exports = mochaHook(cache.exports)
|
|
23
|
+
} else if (id.includes('/node_modules/@cucumber/cucumber/lib/runtime/pickle_runner.js')) {
|
|
24
|
+
cache.exports = pickleHook(cache.exports)
|
|
25
|
+
} else if (id.includes('/node_modules/@cucumber/cucumber/lib/runtime/test_case_runner.js')) {
|
|
26
|
+
cache.exports = testCaseHook(cache.exports)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} catch (e) {
|
|
30
|
+
// ignore error and let the tracer initialize anyway
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
tracer.init(options)
|
|
10
34
|
|
|
11
35
|
tracer.use('fs', false)
|
|
12
36
|
|
package/index.d.ts
CHANGED
|
@@ -108,6 +108,13 @@ export declare interface Tracer extends opentracing.Tracer {
|
|
|
108
108
|
* should not be cached.
|
|
109
109
|
*/
|
|
110
110
|
getRumData(): string;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Links an authenticated user to the current trace.
|
|
114
|
+
* @param {User} user Properties of the authenticated user. Accepts custom fields.
|
|
115
|
+
* @returns {Tracer} The Tracer instance for chaining.
|
|
116
|
+
*/
|
|
117
|
+
setUser(user: User): Tracer;
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
export declare interface TraceOptions extends Analyzable {
|
|
@@ -311,6 +318,7 @@ export declare interface TracerOptions {
|
|
|
311
318
|
*/
|
|
312
319
|
experimental?: boolean | {
|
|
313
320
|
b3?: boolean
|
|
321
|
+
traceparent?: boolean
|
|
314
322
|
|
|
315
323
|
/**
|
|
316
324
|
* Whether to add an auto-generated `runtime-id` tag to metrics.
|
|
@@ -424,6 +432,49 @@ export declare interface TracerOptions {
|
|
|
424
432
|
};
|
|
425
433
|
}
|
|
426
434
|
|
|
435
|
+
/**
|
|
436
|
+
* User object that can be passed to `tracer.setUser()`.
|
|
437
|
+
*/
|
|
438
|
+
export declare interface User {
|
|
439
|
+
/**
|
|
440
|
+
* Unique identifier of the user.
|
|
441
|
+
* Mandatory.
|
|
442
|
+
*/
|
|
443
|
+
id: string,
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Email of the user.
|
|
447
|
+
*/
|
|
448
|
+
email?: string,
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* User-friendly name of the user.
|
|
452
|
+
*/
|
|
453
|
+
name?: string,
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Session ID of the user.
|
|
457
|
+
*/
|
|
458
|
+
session_id?: string,
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Role the user is making the request under.
|
|
462
|
+
*/
|
|
463
|
+
role?: string,
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Scopes or granted authorizations the user currently possesses.
|
|
467
|
+
* The value could come from the scope associated with an OAuth2
|
|
468
|
+
* Access Token or an attribute value in a SAML 2 Assertion.
|
|
469
|
+
*/
|
|
470
|
+
scope?: string,
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Custom fields to attach to the user (RBAC, Oauth, etc…).
|
|
474
|
+
*/
|
|
475
|
+
[key: string]: string | undefined
|
|
476
|
+
}
|
|
477
|
+
|
|
427
478
|
/** @hidden */
|
|
428
479
|
interface EventEmitter {
|
|
429
480
|
emit(eventName: string | symbol, ...args: any[]): any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"node": ">=12"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@datadog/native-appsec": "^0.8.
|
|
64
|
+
"@datadog/native-appsec": "^0.8.3",
|
|
65
65
|
"@datadog/native-metrics": "^1.1.0",
|
|
66
66
|
"@datadog/pprof": "^0.3.0",
|
|
67
67
|
"@datadog/sketches-js": "^1.0.4",
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
require('./src/amqplib')
|
|
4
|
+
require('./src/amqp10')
|
|
3
5
|
require('./src/bluebird')
|
|
4
6
|
require('./src/bunyan')
|
|
7
|
+
require('./src/cassandra-driver')
|
|
5
8
|
require('./src/couchbase')
|
|
6
9
|
require('./src/cucumber')
|
|
7
10
|
require('./src/dns')
|
|
8
11
|
require('./src/elasticsearch')
|
|
9
12
|
require('./src/generic-pool')
|
|
13
|
+
require('./src/http')
|
|
10
14
|
require('./src/ioredis')
|
|
11
15
|
require('./src/memcached')
|
|
16
|
+
require('./src/mongodb-core')
|
|
12
17
|
require('./src/mongoose')
|
|
13
18
|
require('./src/mysql')
|
|
14
19
|
require('./src/mysql2')
|
|
20
|
+
require('./src/mocha')
|
|
21
|
+
require('./src/net')
|
|
15
22
|
require('./src/pino')
|
|
23
|
+
require('./src/pg')
|
|
16
24
|
require('./src/promise')
|
|
17
25
|
require('./src/promise-js')
|
|
18
26
|
require('./src/q')
|
|
19
27
|
require('./src/redis')
|
|
28
|
+
require('./src/rhea')
|
|
20
29
|
require('./src/sharedb')
|
|
30
|
+
require('./src/tedious')
|
|
21
31
|
require('./src/when')
|
|
22
32
|
require('./src/winston')
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
addHook({ name: 'amqp10', file: 'lib/sender_link.js', versions: ['>=3'] }, SenderLink => {
|
|
11
|
+
const startCh = channel('apm:amqp10:send:start')
|
|
12
|
+
const asyncEndCh = channel('apm:amqp10:send:async-end')
|
|
13
|
+
const endCh = channel('apm:amqp10:send:end')
|
|
14
|
+
const errorCh = channel('apm:amqp10:send:error')
|
|
15
|
+
shimmer.wrap(SenderLink.prototype, 'send', send => function (msg, options) {
|
|
16
|
+
if (!startCh.hasSubscribers) {
|
|
17
|
+
return send.apply(this, arguments)
|
|
18
|
+
}
|
|
19
|
+
startCh.publish({ link: this })
|
|
20
|
+
try {
|
|
21
|
+
const promise = send.apply(this, arguments)
|
|
22
|
+
|
|
23
|
+
if (!promise) {
|
|
24
|
+
finish(asyncEndCh, errorCh)
|
|
25
|
+
return promise
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
29
|
+
|
|
30
|
+
promise.then(asyncResource.bind(() => finish(asyncEndCh, errorCh)),
|
|
31
|
+
asyncResource.bind(e => finish(asyncEndCh, errorCh, e)))
|
|
32
|
+
|
|
33
|
+
return promise
|
|
34
|
+
} catch (err) {
|
|
35
|
+
finish(asyncEndCh, errorCh, err)
|
|
36
|
+
throw err
|
|
37
|
+
} finally {
|
|
38
|
+
endCh.publish(undefined)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
return SenderLink
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
addHook({ name: 'amqp10', file: 'lib/receiver_link.js', versions: ['>=3'] }, ReceiverLink => {
|
|
45
|
+
const startCh = channel('apm:amqp10:receive:start')
|
|
46
|
+
const endCh = channel('apm:amqp10:receive:end')
|
|
47
|
+
const errorCh = channel('apm:amqp10:receive:error')
|
|
48
|
+
shimmer.wrap(ReceiverLink.prototype, '_messageReceived', messageReceived => function (transferFrame) {
|
|
49
|
+
if (!transferFrame || transferFrame.aborted || transferFrame.more) {
|
|
50
|
+
return messageReceived.apply(this, arguments)
|
|
51
|
+
}
|
|
52
|
+
startCh.publish({ link: this })
|
|
53
|
+
try {
|
|
54
|
+
return messageReceived.apply(this, arguments)
|
|
55
|
+
} catch (err) {
|
|
56
|
+
errorCh.publish(err)
|
|
57
|
+
throw err
|
|
58
|
+
} finally {
|
|
59
|
+
endCh.publish(undefined)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
return ReceiverLink
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
function finish (asyncEndCh, errorCh, error) {
|
|
66
|
+
if (error) {
|
|
67
|
+
errorCh.publish(error)
|
|
68
|
+
}
|
|
69
|
+
asyncEndCh.publish(undefined)
|
|
70
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook
|
|
6
|
+
} = require('./helpers/instrument')
|
|
7
|
+
const kebabCase = require('lodash.kebabcase')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
const startCh = channel('apm:amqplib:command:start')
|
|
11
|
+
const endCh = channel('apm:amqplib:command:end')
|
|
12
|
+
const errorCh = channel('apm:amqplib:command:error')
|
|
13
|
+
|
|
14
|
+
let methods = {}
|
|
15
|
+
|
|
16
|
+
addHook({ name: 'amqplib', file: 'lib/defs.js', versions: ['>=0.5'] }, defs => {
|
|
17
|
+
methods = Object.keys(defs)
|
|
18
|
+
.filter(key => Number.isInteger(defs[key]))
|
|
19
|
+
.filter(key => isCamelCase(key))
|
|
20
|
+
.reduce((acc, key) => Object.assign(acc, { [defs[key]]: kebabCase(key).replace('-', '.') }), {})
|
|
21
|
+
return defs
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
addHook({ name: 'amqplib', file: 'lib/channel.js', versions: ['>=0.5'] }, channel => {
|
|
25
|
+
shimmer.wrap(channel.Channel.prototype, 'sendImmediately', sendImmediately => function (method, fields) {
|
|
26
|
+
return instrument(sendImmediately, this, arguments, methods[method], fields)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
shimmer.wrap(channel.Channel.prototype, 'sendMessage', sendMessage => function (fields) {
|
|
30
|
+
return instrument(sendMessage, this, arguments, 'basic.publish', fields)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
shimmer.wrap(channel.BaseChannel.prototype, 'dispatchMessage', dispatchMessage => function (fields, message) {
|
|
34
|
+
return instrument(dispatchMessage, this, arguments, 'basic.deliver', fields, message)
|
|
35
|
+
})
|
|
36
|
+
return channel
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
function instrument (send, channel, args, method, fields, message) {
|
|
40
|
+
if (!startCh.hasSubscribers) {
|
|
41
|
+
return send.apply(this, arguments)
|
|
42
|
+
}
|
|
43
|
+
startCh.publish({ channel, method, fields, message })
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
return send.apply(channel, args)
|
|
47
|
+
} catch (err) {
|
|
48
|
+
errorCh.publish(err)
|
|
49
|
+
|
|
50
|
+
throw err
|
|
51
|
+
} finally {
|
|
52
|
+
endCh.publish(undefined)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isCamelCase (str) {
|
|
57
|
+
return /([A-Z][a-z0-9]+)+/.test(str)
|
|
58
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
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 startCh = channel('apm:cassandra:query:start')
|
|
11
|
+
const asyncEndCh = channel('apm:cassandra:query:async-end')
|
|
12
|
+
const endCh = channel('apm:cassandra:query:end')
|
|
13
|
+
const errorCh = channel('apm:cassandra:query:error')
|
|
14
|
+
const addConnectionCh = channel(`apm:cassandra:query:addConnection`)
|
|
15
|
+
|
|
16
|
+
addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
|
|
17
|
+
shimmer.wrap(cassandra.Client.prototype, 'batch', batch => function (queries, options, callback) {
|
|
18
|
+
if (!startCh.hasSubscribers) {
|
|
19
|
+
return batch.apply(this, arguments)
|
|
20
|
+
}
|
|
21
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
22
|
+
startCh.publish({ keyspace: this.keyspace, query: queries })
|
|
23
|
+
|
|
24
|
+
const lastIndex = arguments.length - 1
|
|
25
|
+
let cb = arguments[lastIndex]
|
|
26
|
+
|
|
27
|
+
if (typeof cb === 'function') {
|
|
28
|
+
cb = asyncResource.bind(cb)
|
|
29
|
+
arguments[lastIndex] = wrapCallback(asyncEndCh, errorCh, cb)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const res = batch.apply(this, arguments)
|
|
34
|
+
if (typeof res === 'function' || !res) {
|
|
35
|
+
return wrapCallback(asyncEndCh, errorCh, res)
|
|
36
|
+
} else {
|
|
37
|
+
const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
38
|
+
return res.then(
|
|
39
|
+
promiseAsyncResource.bind(() => finish(asyncEndCh, errorCh)),
|
|
40
|
+
promiseAsyncResource.bind(err => finish(asyncEndCh, errorCh, err))
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
finish(asyncEndCh, errorCh, e)
|
|
45
|
+
throw e
|
|
46
|
+
} finally {
|
|
47
|
+
endCh.publish(undefined)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
return cassandra
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
addHook({ name: 'cassandra-driver', versions: ['>=4.4'] }, cassandra => {
|
|
54
|
+
shimmer.wrap(cassandra.Client.prototype, '_execute', _execute => function (query, params, execOptions, callback) {
|
|
55
|
+
if (!startCh.hasSubscribers) {
|
|
56
|
+
return _execute.apply(this, arguments)
|
|
57
|
+
}
|
|
58
|
+
startCh.publish({ keyspace: this.keyspace, query })
|
|
59
|
+
const promise = _execute.apply(this, arguments)
|
|
60
|
+
|
|
61
|
+
const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
62
|
+
|
|
63
|
+
promise.then(
|
|
64
|
+
promiseAsyncResource.bind(() => finish(asyncEndCh, errorCh)),
|
|
65
|
+
promiseAsyncResource.bind(err => finish(asyncEndCh, errorCh, err))
|
|
66
|
+
)
|
|
67
|
+
endCh.publish(undefined)
|
|
68
|
+
return promise
|
|
69
|
+
})
|
|
70
|
+
return cassandra
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
addHook({ name: 'cassandra-driver', versions: ['3 - 4.3'] }, cassandra => {
|
|
74
|
+
shimmer.wrap(cassandra.Client.prototype, '_innerExecute', _innerExecute =>
|
|
75
|
+
function (query, params, execOptions, callback) {
|
|
76
|
+
if (!startCh.hasSubscribers) {
|
|
77
|
+
return _innerExecute.apply(this, arguments)
|
|
78
|
+
}
|
|
79
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
80
|
+
const isValid = (args) => {
|
|
81
|
+
return args.length === 4 || typeof args[3] === 'function'
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!isValid(arguments)) {
|
|
85
|
+
return _innerExecute.apply(this, arguments)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
startCh.publish({ keyspace: this.keyspace, query })
|
|
89
|
+
|
|
90
|
+
const lastIndex = arguments.length - 1
|
|
91
|
+
let cb = arguments[lastIndex]
|
|
92
|
+
|
|
93
|
+
if (typeof cb === 'function') {
|
|
94
|
+
cb = asyncResource.bind(cb)
|
|
95
|
+
arguments[lastIndex] = wrapCallback(asyncEndCh, errorCh, cb)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
return _innerExecute.apply(this, arguments)
|
|
100
|
+
} catch (e) {
|
|
101
|
+
finish(asyncEndCh, errorCh, e)
|
|
102
|
+
throw e
|
|
103
|
+
} finally {
|
|
104
|
+
endCh.publish(undefined)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
return cassandra
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
addHook({ name: 'cassandra-driver', versions: ['>=3.3'], file: 'lib/request-execution.js' }, RequestExecution => {
|
|
112
|
+
shimmer.wrap(RequestExecution.prototype, '_sendOnConnection', _sendOnConnection => function () {
|
|
113
|
+
if (!startCh.hasSubscribers) {
|
|
114
|
+
return _sendOnConnection.apply(this, arguments)
|
|
115
|
+
}
|
|
116
|
+
addConnectionCh.publish({ address: this._connection.address, port: this._connection.port })
|
|
117
|
+
return _sendOnConnection.apply(this, arguments)
|
|
118
|
+
})
|
|
119
|
+
return RequestExecution
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
addHook({ name: 'cassandra-driver', versions: ['3.3 - 4.3'], file: 'lib/request-execution.js' }, RequestExecution => {
|
|
123
|
+
shimmer.wrap(RequestExecution.prototype, 'start', start => function (getHostCallback) {
|
|
124
|
+
if (!startCh.hasSubscribers) {
|
|
125
|
+
return getHostCallback.apply(this, arguments)
|
|
126
|
+
}
|
|
127
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
128
|
+
const execution = this
|
|
129
|
+
|
|
130
|
+
if (!isRequestValid(this, arguments, 1)) {
|
|
131
|
+
return start.apply(this, arguments)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
getHostCallback = asyncResource.bind(getHostCallback)
|
|
135
|
+
|
|
136
|
+
arguments[0] = AsyncResource.bind(function () {
|
|
137
|
+
addConnectionCh.publish({ address: execution._connection.address, port: execution._connection.port })
|
|
138
|
+
return getHostCallback.apply(this, arguments)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
return start.apply(this, arguments)
|
|
142
|
+
})
|
|
143
|
+
return RequestExecution
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
addHook({ name: 'cassandra-driver', versions: ['3 - 3.2'], file: 'lib/request-handler.js' }, RequestHandler => {
|
|
147
|
+
shimmer.wrap(RequestHandler.prototype, 'send', send => function (request, options, callback) {
|
|
148
|
+
if (!startCh.hasSubscribers) {
|
|
149
|
+
return send.apply(this, arguments)
|
|
150
|
+
}
|
|
151
|
+
const handler = this
|
|
152
|
+
|
|
153
|
+
if (!isRequestValid(this, arguments, 3)) {
|
|
154
|
+
return send.apply(this, arguments)
|
|
155
|
+
}
|
|
156
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
157
|
+
|
|
158
|
+
callback = asyncResource.bind(callback)
|
|
159
|
+
|
|
160
|
+
arguments[2] = AsyncResource.bind(function () {
|
|
161
|
+
addConnectionCh.publish({ address: handler.connection.address, port: handler.connection.port })
|
|
162
|
+
return callback.apply(this, arguments)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
return send.apply(this, arguments)
|
|
166
|
+
})
|
|
167
|
+
return RequestHandler
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
function finish (asyncEndCh, errorCh, error) {
|
|
171
|
+
if (error) {
|
|
172
|
+
errorCh.publish(error)
|
|
173
|
+
}
|
|
174
|
+
asyncEndCh.publish(undefined)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function wrapCallback (asyncEndCh, errorCh, callback) {
|
|
178
|
+
return AsyncResource.bind(function (err) {
|
|
179
|
+
finish(asyncEndCh, errorCh, err)
|
|
180
|
+
if (callback) {
|
|
181
|
+
return callback.apply(this, arguments)
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isRequestValid (exec, args, length) {
|
|
187
|
+
if (!exec) return false
|
|
188
|
+
if (args.length !== length || typeof args[length - 1] !== 'function') return false
|
|
189
|
+
|
|
190
|
+
return true
|
|
191
|
+
}
|
|
@@ -10,6 +10,9 @@ const runStepStartCh = channel('ci:cucumber:run-step:start')
|
|
|
10
10
|
const runStepEndCh = channel('ci:cucumber:run-step:end')
|
|
11
11
|
const errorCh = channel('ci:cucumber:error')
|
|
12
12
|
|
|
13
|
+
// TODO: remove in a later major version
|
|
14
|
+
const patched = new WeakSet()
|
|
15
|
+
|
|
13
16
|
function getStatusFromResult (result) {
|
|
14
17
|
if (result.status === 1) {
|
|
15
18
|
return { status: 'pass' }
|
|
@@ -37,6 +40,10 @@ function getStatusFromResultLatest (result) {
|
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
function wrapRun (pl, isLatestVersion) {
|
|
43
|
+
if (patched.has(pl)) return
|
|
44
|
+
|
|
45
|
+
patched.add(pl)
|
|
46
|
+
|
|
40
47
|
shimmer.wrap(pl.prototype, 'run', run => function () {
|
|
41
48
|
if (!runStartCh.hasSubscribers) {
|
|
42
49
|
return run.apply(this, arguments)
|
|
@@ -55,6 +62,7 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
55
62
|
return promise
|
|
56
63
|
} catch (err) {
|
|
57
64
|
errorCh.publish(err)
|
|
65
|
+
throw err
|
|
58
66
|
} finally {
|
|
59
67
|
runEndCh.publish(undefined)
|
|
60
68
|
}
|
|
@@ -85,32 +93,39 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
85
93
|
return promise
|
|
86
94
|
} catch (err) {
|
|
87
95
|
errorCh.publish(err)
|
|
96
|
+
throw err
|
|
88
97
|
} finally {
|
|
89
98
|
runStepEndCh.publish(undefined)
|
|
90
99
|
}
|
|
91
100
|
})
|
|
92
101
|
}
|
|
93
102
|
|
|
94
|
-
|
|
95
|
-
name: '@cucumber/cucumber',
|
|
96
|
-
versions: ['7.0.0 - 7.2.1'],
|
|
97
|
-
file: 'lib/runtime/pickle_runner.js'
|
|
98
|
-
}, (PickleRunner) => {
|
|
103
|
+
function pickleHook (PickleRunner) {
|
|
99
104
|
const pl = PickleRunner.default
|
|
100
105
|
|
|
101
106
|
wrapRun(pl, false)
|
|
102
107
|
|
|
103
108
|
return PickleRunner
|
|
104
|
-
}
|
|
109
|
+
}
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
name: '@cucumber/cucumber',
|
|
108
|
-
versions: ['>=7.3.0'],
|
|
109
|
-
file: 'lib/runtime/test_case_runner.js'
|
|
110
|
-
}, (TestCaseRunner) => {
|
|
111
|
+
function testCaseHook (TestCaseRunner) {
|
|
111
112
|
const pl = TestCaseRunner.default
|
|
112
113
|
|
|
113
114
|
wrapRun(pl, true)
|
|
114
115
|
|
|
115
116
|
return TestCaseRunner
|
|
116
|
-
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
addHook({
|
|
120
|
+
name: '@cucumber/cucumber',
|
|
121
|
+
versions: ['7.0.0 - 7.2.1'],
|
|
122
|
+
file: 'lib/runtime/pickle_runner.js'
|
|
123
|
+
}, pickleHook)
|
|
124
|
+
|
|
125
|
+
addHook({
|
|
126
|
+
name: '@cucumber/cucumber',
|
|
127
|
+
versions: ['>=7.3.0'],
|
|
128
|
+
file: 'lib/runtime/test_case_runner.js'
|
|
129
|
+
}, testCaseHook)
|
|
130
|
+
|
|
131
|
+
module.exports = { pickleHook, testCaseHook }
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const iitm = require('../../../dd-trace/src/iitm')
|
|
5
|
+
const ritm = require('../../../dd-trace/src/ritm')
|
|
6
|
+
|
|
7
|
+
function Hook (modules, onrequire) {
|
|
8
|
+
if (!(this instanceof Hook)) return new Hook(modules, onrequire)
|
|
9
|
+
|
|
10
|
+
this._patched = Object.create(null)
|
|
11
|
+
|
|
12
|
+
const safeHook = (moduleExports, moduleName, moduleBaseDir) => {
|
|
13
|
+
const parts = [moduleBaseDir, moduleName].filter(v => v)
|
|
14
|
+
const filename = path.join(...parts)
|
|
15
|
+
|
|
16
|
+
if (this._patched[filename]) return moduleExports
|
|
17
|
+
|
|
18
|
+
this._patched[filename] = true
|
|
19
|
+
|
|
20
|
+
return onrequire(moduleExports, moduleName, moduleBaseDir)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this._ritmHook = ritm(modules, {}, safeHook)
|
|
24
|
+
this._iitmHook = iitm(modules, {}, (moduleExports, moduleName, moduleBaseDir) => {
|
|
25
|
+
// TODO: Move this logic to import-in-the-middle and only do it for CommonJS
|
|
26
|
+
// modules and not ESM. In the meantime, all the modules we instrument are
|
|
27
|
+
// CommonJS modules for which the default export is always moved to
|
|
28
|
+
// `default` anyway.
|
|
29
|
+
if (moduleExports && moduleExports.default) {
|
|
30
|
+
moduleExports.default = safeHook(moduleExports.default, moduleName, moduleBaseDir)
|
|
31
|
+
return moduleExports
|
|
32
|
+
} else {
|
|
33
|
+
return safeHook(moduleExports, moduleName, moduleBaseDir)
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Hook.prototype.unhook = function () {
|
|
39
|
+
this._ritmHook.unhook()
|
|
40
|
+
this._iitmHook.unhook()
|
|
41
|
+
this._patched = Object.create(null)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = Hook
|