dd-trace 2.3.1 → 2.4.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/index.d.ts +51 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/index.js +8 -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 +2 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +3 -3
- package/packages/datadog-instrumentations/src/mocha.js +122 -0
- package/packages/datadog-instrumentations/src/mongodb-core.js +179 -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-cassandra-driver/src/index.js +52 -224
- package/packages/datadog-plugin-cucumber/src/index.js +3 -1
- 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-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/noop/tracer.js +4 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +34 -1
- package/packages/dd-trace/src/proxy.js +4 -0
- 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
|
@@ -0,0 +1,179 @@
|
|
|
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:mongodb:query:start`)
|
|
11
|
+
const endCh = channel(`apm:mongodb:query:end`)
|
|
12
|
+
const asyncEndCh = channel(`apm:mongodb:query:async-end`)
|
|
13
|
+
const errorCh = channel(`apm:mongodb:query:error`)
|
|
14
|
+
|
|
15
|
+
addHook({ name: 'mongodb-core', versions: ['2 - 3.1.9'] }, Server => {
|
|
16
|
+
const serverProto = Server.Server.prototype
|
|
17
|
+
shimmer.wrap(serverProto, 'command', command => wrapCommand(command, 'command'))
|
|
18
|
+
shimmer.wrap(serverProto, 'insert', insert => wrapCommand(insert, 'insert', 'insert'))
|
|
19
|
+
shimmer.wrap(serverProto, 'update', update => wrapCommand(update, 'update', 'update'))
|
|
20
|
+
shimmer.wrap(serverProto, 'remove', remove => wrapCommand(remove, 'remove', 'remove'))
|
|
21
|
+
|
|
22
|
+
const cursorProto = Server.Cursor.prototype
|
|
23
|
+
shimmer.wrap(cursorProto, '_getmore', _getmore => wrapCursor(_getmore, 'getMore', 'getMore'))
|
|
24
|
+
shimmer.wrap(cursorProto, '_find', _find => wrapQuery(_find, '_find'))
|
|
25
|
+
shimmer.wrap(cursorProto, 'kill', kill => wrapCursor(kill, 'killCursors', 'killCursors'))
|
|
26
|
+
return Server
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
addHook({ name: 'mongodb', versions: ['>=4'], file: 'lib/cmap/connection.js' }, Connection => {
|
|
30
|
+
const proto = Connection.Connection.prototype
|
|
31
|
+
shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
|
|
32
|
+
shimmer.wrap(proto, 'query', query => wrapConnectionCommand(query, 'query'))
|
|
33
|
+
return Connection
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
addHook({ name: 'mongodb', versions: ['>=3.3 <4'], file: 'lib/core/wireprotocol/index.js' }, wp => wrapWp(wp))
|
|
37
|
+
|
|
38
|
+
addHook({ name: 'mongodb-core', versions: ['>=3.2'], file: 'lib/wireprotocol/index.js' }, wp => wrapWp(wp))
|
|
39
|
+
|
|
40
|
+
addHook({ name: 'mongodb-core', versions: ['~3.1.10'], file: 'lib/wireprotocol/3_2_support.js' }, WireProtocol => {
|
|
41
|
+
shimmer.wrap(WireProtocol.prototype, 'command', command => wrapUnifiedCommand(command, 'command'))
|
|
42
|
+
return WireProtocol
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
addHook({ name: 'mongodb-core', versions: ['~3.1.10'], file: 'lib/wireprotocol/2_6_support.js' }, WireProtocol => {
|
|
46
|
+
shimmer.wrap(WireProtocol.prototype, 'command', command => wrapUnifiedCommand(command, 'command'))
|
|
47
|
+
return WireProtocol
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
addHook({ name: 'mongodb', versions: ['>=3.5.4'], file: 'lib/utils.js' }, util => {
|
|
51
|
+
shimmer.wrap(util, 'maybePromise', maybePromise => function (parent, callback, fn) {
|
|
52
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
53
|
+
const callbackIndex = arguments.length - 2
|
|
54
|
+
|
|
55
|
+
callback = arguments[callbackIndex]
|
|
56
|
+
|
|
57
|
+
if (typeof callback === 'function') {
|
|
58
|
+
arguments[callbackIndex] = asyncResource.bind(callback)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return maybePromise.apply(this, arguments)
|
|
62
|
+
})
|
|
63
|
+
return util
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
function wrapWp (wp) {
|
|
67
|
+
shimmer.wrap(wp, 'command', command => wrapUnifiedCommand(command, 'command'))
|
|
68
|
+
shimmer.wrap(wp, 'insert', insert => wrapUnifiedCommand(insert, 'insert', 'insert'))
|
|
69
|
+
shimmer.wrap(wp, 'update', update => wrapUnifiedCommand(update, 'update', 'update'))
|
|
70
|
+
shimmer.wrap(wp, 'remove', remove => wrapUnifiedCommand(remove, 'remove', 'remove'))
|
|
71
|
+
shimmer.wrap(wp, 'query', query => wrapUnifiedCommand(query, 'query'))
|
|
72
|
+
shimmer.wrap(wp, 'getMore', getMore => wrapUnifiedCommand(getMore, 'getMore', 'getMore'))
|
|
73
|
+
shimmer.wrap(wp, 'killCursors', killCursors => wrapUnifiedCommand(killCursors, 'killCursors', 'killCursors'))
|
|
74
|
+
return wp
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function wrapUnifiedCommand (command, operation, name) {
|
|
78
|
+
const wrapped = function (server, ns, ops) {
|
|
79
|
+
if (!startCh.hasSubscribers) {
|
|
80
|
+
return command.apply(this, arguments)
|
|
81
|
+
}
|
|
82
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
83
|
+
return instrument(asyncResource, operation, command, this, arguments, server, ns, ops, { name })
|
|
84
|
+
}
|
|
85
|
+
return shimmer.wrap(command, wrapped)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function wrapConnectionCommand (command, operation, name) {
|
|
89
|
+
const wrapped = function (ns, ops) {
|
|
90
|
+
if (!startCh.hasSubscribers) {
|
|
91
|
+
return command.apply(this, arguments)
|
|
92
|
+
}
|
|
93
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
94
|
+
const hostParts = typeof this.address === 'string' ? this.address.split(':') : ''
|
|
95
|
+
const options = hostParts.length === 2
|
|
96
|
+
? { host: hostParts[0], port: hostParts[1] }
|
|
97
|
+
: {} // no port means the address is a random UUID so no host either
|
|
98
|
+
const topology = { s: { options } }
|
|
99
|
+
|
|
100
|
+
ns = `${ns.db}.${ns.collection}`
|
|
101
|
+
return instrument(asyncResource, operation, command, this, arguments, topology, ns, ops, { name })
|
|
102
|
+
}
|
|
103
|
+
return shimmer.wrap(command, wrapped)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function wrapQuery (query, operation, name) {
|
|
107
|
+
const wrapped = function () {
|
|
108
|
+
if (!startCh.hasSubscribers) {
|
|
109
|
+
return query.apply(this, arguments)
|
|
110
|
+
}
|
|
111
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
112
|
+
const pool = this.server.s.pool
|
|
113
|
+
const ns = this.ns
|
|
114
|
+
const ops = this.cmd
|
|
115
|
+
return instrument(asyncResource, operation, query, this, arguments, pool, ns, ops)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return shimmer.wrap(query, wrapped)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function wrapCursor (cursor, operation, name) {
|
|
122
|
+
const wrapped = function () {
|
|
123
|
+
if (!startCh.hasSubscribers) {
|
|
124
|
+
return cursor.apply(this, arguments)
|
|
125
|
+
}
|
|
126
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
127
|
+
const pool = this.server.s.pool
|
|
128
|
+
const ns = this.ns
|
|
129
|
+
return instrument(asyncResource, operation, cursor, this, arguments, pool, ns, {}, { name })
|
|
130
|
+
}
|
|
131
|
+
return shimmer.wrap(cursor, wrapped)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function wrapCommand (command, operation, name) {
|
|
135
|
+
const wrapped = function (ns, ops) {
|
|
136
|
+
if (!startCh.hasSubscribers) {
|
|
137
|
+
return command.apply(this, arguments)
|
|
138
|
+
}
|
|
139
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
140
|
+
return instrument(asyncResource, operation, command, this, arguments, this, ns, ops, { name })
|
|
141
|
+
}
|
|
142
|
+
return shimmer.wrap(command, wrapped)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function instrument (ar, operation, command, ctx, args, server, ns, ops, options = {}) {
|
|
146
|
+
const name = options.name || (ops && Object.keys(ops)[0])
|
|
147
|
+
const index = args.length - 1
|
|
148
|
+
let callback = args[index]
|
|
149
|
+
|
|
150
|
+
if (typeof callback !== 'function') return command.apply(ctx, args)
|
|
151
|
+
|
|
152
|
+
callback = ar.bind(callback)
|
|
153
|
+
|
|
154
|
+
const serverInfo = server && server.s && server.s.options
|
|
155
|
+
|
|
156
|
+
startCh.publish({ ns, ops, options: serverInfo, name })
|
|
157
|
+
|
|
158
|
+
args[index] = AsyncResource.bind(function (err, res) {
|
|
159
|
+
if (err) {
|
|
160
|
+
errorCh.publish(err)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
asyncEndCh.publish(undefined)
|
|
164
|
+
|
|
165
|
+
if (callback) {
|
|
166
|
+
return callback.apply(this, arguments)
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
return command.apply(ctx, args)
|
|
172
|
+
} catch (err) {
|
|
173
|
+
errorCh.publish(err)
|
|
174
|
+
|
|
175
|
+
throw err
|
|
176
|
+
} finally {
|
|
177
|
+
endCh.publish(undefined)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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:pg:query:start')
|
|
11
|
+
const asyncEndCh = channel('apm:pg:query:async-end')
|
|
12
|
+
const endCh = channel('apm:pg:query:end')
|
|
13
|
+
const errorCh = channel('apm:pg:query:error')
|
|
14
|
+
|
|
15
|
+
addHook({ name: 'pg', versions: ['>=4'] }, pg => {
|
|
16
|
+
shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
|
|
17
|
+
return pg
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=4'] }, Client => {
|
|
21
|
+
shimmer.wrap(Client.prototype, 'query', query => wrapQuery(query))
|
|
22
|
+
return Client
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
function wrapQuery (query) {
|
|
26
|
+
return function () {
|
|
27
|
+
if (!startCh.hasSubscribers) {
|
|
28
|
+
return query.apply(this, arguments)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
32
|
+
|
|
33
|
+
const retval = query.apply(this, arguments)
|
|
34
|
+
|
|
35
|
+
const queryQueue = this.queryQueue || this._queryQueue
|
|
36
|
+
const activeQuery = this.activeQuery || this._activeQuery
|
|
37
|
+
const pgQuery = queryQueue[queryQueue.length - 1] || activeQuery
|
|
38
|
+
|
|
39
|
+
if (!pgQuery) {
|
|
40
|
+
return retval
|
|
41
|
+
}
|
|
42
|
+
const statement = pgQuery.text
|
|
43
|
+
|
|
44
|
+
startCh.publish({ params: this.connectionParameters, statement })
|
|
45
|
+
|
|
46
|
+
const finish = AsyncResource.bind(function (error) {
|
|
47
|
+
if (error) {
|
|
48
|
+
errorCh.publish(error)
|
|
49
|
+
}
|
|
50
|
+
asyncEndCh.publish(undefined)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
if (pgQuery.callback) {
|
|
54
|
+
const originalCallback = asyncResource.bind(pgQuery.callback)
|
|
55
|
+
pgQuery.callback = function (err, res) {
|
|
56
|
+
finish(err)
|
|
57
|
+
return originalCallback.apply(this, arguments)
|
|
58
|
+
}
|
|
59
|
+
} else if (pgQuery.once) {
|
|
60
|
+
pgQuery
|
|
61
|
+
.once('error', finish)
|
|
62
|
+
.once('end', () => finish())
|
|
63
|
+
} else {
|
|
64
|
+
pgQuery.then(() => finish(), finish)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
return retval
|
|
69
|
+
} catch (err) {
|
|
70
|
+
errorCh.publish(err)
|
|
71
|
+
} finally {
|
|
72
|
+
endCh.publish(undefined)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
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 circularBufferConstructor = Symbol('circularBufferConstructor')
|
|
11
|
+
const inFlightDeliveries = Symbol('inFlightDeliveries')
|
|
12
|
+
|
|
13
|
+
const patched = new WeakSet()
|
|
14
|
+
const dispatchCh = channel('apm:rhea:dispatch')
|
|
15
|
+
const errorCh = channel('apm:rhea:error')
|
|
16
|
+
const asyncEndCh = channel('apm:rhea:async-end')
|
|
17
|
+
const endCh = channel('apm:rhea:end')
|
|
18
|
+
|
|
19
|
+
const contexts = new WeakMap()
|
|
20
|
+
|
|
21
|
+
addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
|
|
22
|
+
const startSendCh = channel('apm:rhea:send:start')
|
|
23
|
+
const startReceiveCh = channel('apm:rhea:receive:start')
|
|
24
|
+
|
|
25
|
+
const Sender = obj.Sender
|
|
26
|
+
const Receiver = obj.Receiver
|
|
27
|
+
shimmer.wrap(Sender.prototype, 'send', send => function (msg, tag, format) {
|
|
28
|
+
if (!canTrace(this)) {
|
|
29
|
+
// we can't handle disconnects or ending spans, so we can't safely instrument
|
|
30
|
+
return send.apply(this, arguments)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const { host, port } = getHostAndPort(this.connection)
|
|
34
|
+
|
|
35
|
+
const targetAddress = this.options && this.options.target &&
|
|
36
|
+
this.options.target.address ? this.options.target.address : undefined
|
|
37
|
+
|
|
38
|
+
startSendCh.publish({ targetAddress, host, port, msg })
|
|
39
|
+
const delivery = send.apply(this, arguments)
|
|
40
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
41
|
+
const context = {
|
|
42
|
+
asyncResource
|
|
43
|
+
}
|
|
44
|
+
contexts.set(delivery, context)
|
|
45
|
+
|
|
46
|
+
addToInFlightDeliveries(this.connection, delivery)
|
|
47
|
+
try {
|
|
48
|
+
return delivery
|
|
49
|
+
} catch (err) {
|
|
50
|
+
errorCh.publish(err)
|
|
51
|
+
|
|
52
|
+
throw err
|
|
53
|
+
} finally {
|
|
54
|
+
endCh.publish(undefined)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
shimmer.wrap(Receiver.prototype, 'dispatch', dispatch => function (eventName, msgObj) {
|
|
59
|
+
if (!canTrace(this)) {
|
|
60
|
+
// we can't handle disconnects or ending spans, so we can't safely instrument
|
|
61
|
+
return dispatch.apply(this, arguments)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (eventName === 'message' && msgObj) {
|
|
65
|
+
startReceiveCh.publish({ msgObj, connection: this.connection })
|
|
66
|
+
|
|
67
|
+
if (msgObj.delivery) {
|
|
68
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
69
|
+
const context = {
|
|
70
|
+
asyncResource
|
|
71
|
+
}
|
|
72
|
+
contexts.set(msgObj.delivery, context)
|
|
73
|
+
msgObj.delivery.update = wrapDeliveryUpdate(msgObj.delivery, msgObj.delivery.update)
|
|
74
|
+
addToInFlightDeliveries(this.connection, msgObj.delivery)
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
return dispatch.apply(this, arguments)
|
|
78
|
+
} catch (err) {
|
|
79
|
+
errorCh.publish(err)
|
|
80
|
+
|
|
81
|
+
throw err
|
|
82
|
+
} finally {
|
|
83
|
+
endCh.publish(undefined)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return dispatch.apply(this, arguments)
|
|
88
|
+
})
|
|
89
|
+
return obj
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/connection.js' }, Connection => {
|
|
93
|
+
shimmer.wrap(Connection.prototype, 'dispatch', dispatch => function (eventName, obj) {
|
|
94
|
+
if (eventName === 'disconnected') {
|
|
95
|
+
const error = obj.error || this.saved_error
|
|
96
|
+
if (this[inFlightDeliveries]) {
|
|
97
|
+
this[inFlightDeliveries].forEach(delivery => {
|
|
98
|
+
const context = contexts.get(delivery)
|
|
99
|
+
const asyncResource = context.asyncResource
|
|
100
|
+
asyncResource.runInAsyncScope(() => {
|
|
101
|
+
errorCh.publish(error)
|
|
102
|
+
finish(delivery, null)
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return dispatch.apply(this, arguments)
|
|
108
|
+
})
|
|
109
|
+
return Connection
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/session.js' }, (Session) => {
|
|
113
|
+
patchCircularBuffer(Session.prototype, Session)
|
|
114
|
+
return Session
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
function canTrace (link) {
|
|
118
|
+
return link.connection && link.session && link.session.outgoing
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function getHostAndPort (connection) {
|
|
122
|
+
let host
|
|
123
|
+
let port
|
|
124
|
+
if (connection && connection.options) {
|
|
125
|
+
host = connection.options.host
|
|
126
|
+
port = connection.options.port
|
|
127
|
+
}
|
|
128
|
+
return { host, port }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function wrapDeliveryUpdate (obj, update) {
|
|
132
|
+
const context = contexts.get(obj)
|
|
133
|
+
const asyncResource = context.asyncResource
|
|
134
|
+
if (obj && asyncResource) {
|
|
135
|
+
const cb = asyncResource.bind(update)
|
|
136
|
+
return AsyncResource.bind(function wrappedUpdate (settled, stateData) {
|
|
137
|
+
const state = getStateFromData(stateData)
|
|
138
|
+
dispatchCh.publish({ state })
|
|
139
|
+
return cb.apply(this, arguments)
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
return function wrappedUpdate (settled, stateData) {
|
|
143
|
+
return update.apply(this, arguments)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function patchCircularBuffer (proto, Session) {
|
|
148
|
+
Object.defineProperty(proto, 'outgoing', {
|
|
149
|
+
configurable: true,
|
|
150
|
+
get () {},
|
|
151
|
+
set (outgoing) {
|
|
152
|
+
delete proto.outgoing // removes the setter on the prototype
|
|
153
|
+
this.outgoing = outgoing // assigns on the instance, like normal
|
|
154
|
+
if (outgoing) {
|
|
155
|
+
let CircularBuffer
|
|
156
|
+
if (outgoing.deliveries) {
|
|
157
|
+
CircularBuffer = outgoing.deliveries.constructor
|
|
158
|
+
}
|
|
159
|
+
if (CircularBuffer && !patched.has(CircularBuffer.prototype)) {
|
|
160
|
+
shimmer.wrap(CircularBuffer.prototype, 'pop_if', popIf => function (fn) {
|
|
161
|
+
arguments[0] = AsyncResource.bind(function (entry) {
|
|
162
|
+
const context = contexts.get(entry)
|
|
163
|
+
const asyncResource = context.asyncResource
|
|
164
|
+
let shouldPop
|
|
165
|
+
if (asyncResource) {
|
|
166
|
+
fn = asyncResource.bind(fn, this)
|
|
167
|
+
shouldPop = fn(entry)
|
|
168
|
+
if (shouldPop && asyncResource) {
|
|
169
|
+
const remoteState = entry.remote_state
|
|
170
|
+
const state = remoteState && remoteState.constructor
|
|
171
|
+
? entry.remote_state.constructor.composite_type : undefined
|
|
172
|
+
asyncResource.runInAsyncScope(() => {
|
|
173
|
+
return finish(entry, state)
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return shouldPop
|
|
179
|
+
})
|
|
180
|
+
return popIf.apply(this, arguments)
|
|
181
|
+
})
|
|
182
|
+
patched.add(CircularBuffer.prototype)
|
|
183
|
+
const Session = proto.constructor
|
|
184
|
+
if (Session) {
|
|
185
|
+
Session[circularBufferConstructor] = CircularBuffer
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function addToInFlightDeliveries (connection, delivery) {
|
|
194
|
+
let deliveries = connection[inFlightDeliveries]
|
|
195
|
+
if (!deliveries) {
|
|
196
|
+
deliveries = new Set()
|
|
197
|
+
connection[inFlightDeliveries] = deliveries
|
|
198
|
+
}
|
|
199
|
+
deliveries.add(delivery)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function finish (delivery, state) {
|
|
203
|
+
const obj = contexts.get(delivery)
|
|
204
|
+
if (obj) {
|
|
205
|
+
if (state) {
|
|
206
|
+
dispatchCh.publish({ state })
|
|
207
|
+
}
|
|
208
|
+
asyncEndCh.publish(undefined)
|
|
209
|
+
if (obj.connection && obj.connection[inFlightDeliveries]) {
|
|
210
|
+
obj.connection[inFlightDeliveries].delete(delivery)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getStateFromData (stateData) {
|
|
216
|
+
if (stateData && stateData.descriptor && stateData.descriptor) {
|
|
217
|
+
switch (stateData.descriptor.value) {
|
|
218
|
+
case 0x24: return 'accepted'
|
|
219
|
+
case 0x25: return 'rejected'
|
|
220
|
+
case 0x26: return 'released'
|
|
221
|
+
case 0x27: return 'modified'
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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: 'tedious', versions: [ '>=1.0.0' ] }, tedious => {
|
|
11
|
+
const startCh = channel('apm:tedious:request:start')
|
|
12
|
+
const asyncEndCh = channel('apm:tedious:request:async-end')
|
|
13
|
+
const endCh = channel('apm:tedious:request:end')
|
|
14
|
+
const errorCh = channel('apm:tedious:request:error')
|
|
15
|
+
shimmer.wrap(tedious.Connection.prototype, 'makeRequest', makeRequest => function (request) {
|
|
16
|
+
if (!startCh.hasSubscribers) {
|
|
17
|
+
return request.apply(this, arguments)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const queryOrProcedure = getQueryOrProcedure(request)
|
|
21
|
+
|
|
22
|
+
if (!queryOrProcedure) {
|
|
23
|
+
return makeRequest.apply(this, arguments)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
27
|
+
|
|
28
|
+
const connectionConfig = this.config
|
|
29
|
+
|
|
30
|
+
startCh.publish({ queryOrProcedure, connectionConfig })
|
|
31
|
+
|
|
32
|
+
const cb = asyncResource.bind(request.callback, request)
|
|
33
|
+
request.callback = AsyncResource.bind(function (error) {
|
|
34
|
+
if (error) {
|
|
35
|
+
errorCh.publish(error)
|
|
36
|
+
}
|
|
37
|
+
asyncEndCh.publish(undefined)
|
|
38
|
+
|
|
39
|
+
return cb.apply(this, arguments)
|
|
40
|
+
}, null, request)
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
return makeRequest.apply(this, arguments)
|
|
44
|
+
} catch (error) {
|
|
45
|
+
errorCh.publish(error)
|
|
46
|
+
|
|
47
|
+
throw error
|
|
48
|
+
} finally {
|
|
49
|
+
endCh.publish(undefined)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
return tedious
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
function getQueryOrProcedure (request) {
|
|
57
|
+
if (!request.parameters) return
|
|
58
|
+
|
|
59
|
+
const statement = request.parametersByName.statement || request.parametersByName.stmt
|
|
60
|
+
|
|
61
|
+
if (!statement) {
|
|
62
|
+
return request.sqlTextOrProcedure
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return statement.value
|
|
66
|
+
}
|