dd-trace 2.3.1 → 2.4.2
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-cassandra-driver/src/index.js +52 -224
- package/packages/datadog-plugin-cucumber/src/index.js +3 -1
- package/packages/datadog-plugin-elasticsearch/src/index.js +4 -2
- package/packages/datadog-plugin-http/src/client.js +112 -252
- package/packages/datadog-plugin-http/src/index.js +29 -3
- package/packages/datadog-plugin-http/src/server.js +54 -32
- package/packages/datadog-plugin-jest/src/jest-environment.js +3 -3
- 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 +235 -315
- 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
|
@@ -0,0 +1,117 @@
|
|
|
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 startICPCh = channel('apm:net:ipc:start')
|
|
11
|
+
const asyncICPEndCh = channel('apm:net:ipc:async-end')
|
|
12
|
+
const endICPCh = channel('apm:net:ipc:end')
|
|
13
|
+
const errorICPCh = channel('apm:net:ipc:error')
|
|
14
|
+
|
|
15
|
+
const startTCPCh = channel('apm:net:tcp:start')
|
|
16
|
+
const asyncTCPEndCh = channel('apm:net:tcp:async-end')
|
|
17
|
+
const endTCPCh = channel('apm:net:tcp:end')
|
|
18
|
+
const errorTCPCh = channel('apm:net:tcp:error')
|
|
19
|
+
|
|
20
|
+
const connectionCh = channel(`apm:net:tcp:connection`)
|
|
21
|
+
|
|
22
|
+
addHook({ name: 'net' }, net => {
|
|
23
|
+
require('dns')
|
|
24
|
+
|
|
25
|
+
shimmer.wrap(net.Socket.prototype, 'connect', connect => function () {
|
|
26
|
+
if (!startICPCh.hasSubscribers || !startTCPCh.hasSubscribers) {
|
|
27
|
+
return connect.apply(this, arguments)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const options = getOptions(arguments)
|
|
31
|
+
const lastIndex = arguments.length - 1
|
|
32
|
+
const callback = arguments[lastIndex]
|
|
33
|
+
|
|
34
|
+
if (!options) return connect.apply(this, arguments)
|
|
35
|
+
|
|
36
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
37
|
+
|
|
38
|
+
if (typeof callback === 'function') {
|
|
39
|
+
arguments[lastIndex] = asyncResource.bind(callback)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const protocol = options.path ? 'ipc' : 'tcp'
|
|
43
|
+
|
|
44
|
+
if (protocol === 'ipc') {
|
|
45
|
+
startICPCh.publish({ options })
|
|
46
|
+
setupListeners(this, 'ipc', asyncResource)
|
|
47
|
+
} else {
|
|
48
|
+
startTCPCh.publish({ options })
|
|
49
|
+
setupListeners(this, 'tcp', asyncResource)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
return connect.apply(this, arguments)
|
|
54
|
+
} catch (err) {
|
|
55
|
+
protocol === 'ipc' ? errorICPCh.publish(err) : errorTCPCh.publish(err)
|
|
56
|
+
|
|
57
|
+
throw err
|
|
58
|
+
} finally {
|
|
59
|
+
protocol === 'ipc' ? endICPCh.publish(undefined) : endTCPCh.publish(undefined)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return net
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
function getOptions (args) {
|
|
67
|
+
if (!args[0]) return
|
|
68
|
+
|
|
69
|
+
switch (typeof args[0]) {
|
|
70
|
+
case 'object':
|
|
71
|
+
if (Array.isArray(args[0])) return getOptions(args[0])
|
|
72
|
+
return args[0]
|
|
73
|
+
case 'string':
|
|
74
|
+
if (isNaN(parseFloat(args[0]))) {
|
|
75
|
+
return {
|
|
76
|
+
path: args[0]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
case 'number': // eslint-disable-line no-fallthrough
|
|
80
|
+
return {
|
|
81
|
+
port: args[0],
|
|
82
|
+
host: typeof args[1] === 'string' ? args[1] : 'localhost'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function setupListeners (socket, protocol, ar) {
|
|
88
|
+
const events = ['connect', 'error', 'close', 'timeout']
|
|
89
|
+
|
|
90
|
+
const wrapListener = AsyncResource.bind(function (error) {
|
|
91
|
+
if (error) {
|
|
92
|
+
protocol === 'ipc' ? errorICPCh.publish(error) : errorTCPCh.publish(error)
|
|
93
|
+
}
|
|
94
|
+
protocol === 'ipc' ? asyncICPEndCh.publish(undefined) : asyncTCPEndCh.publish(undefined)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const localListener = AsyncResource.bind(function () {
|
|
98
|
+
connectionCh.publish({ socket })
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const cleanupListener = function () {
|
|
102
|
+
socket.removeListener('connect', localListener)
|
|
103
|
+
events.forEach(event => {
|
|
104
|
+
socket.removeListener(event, wrapListener)
|
|
105
|
+
socket.removeListener(event, cleanupListener)
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (protocol === 'tcp') {
|
|
110
|
+
socket.once('connect', localListener)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
events.forEach(event => {
|
|
114
|
+
socket.once(event, wrapListener)
|
|
115
|
+
socket.once(event, cleanupListener)
|
|
116
|
+
})
|
|
117
|
+
}
|
|
@@ -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
|
+
}
|