newrelic 7.5.2 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/NEWS.md +4989 -4886
  2. package/THIRD_PARTY_NOTICES.md +625 -216
  3. package/api.js +105 -174
  4. package/bin/test-naming-rules.js +38 -32
  5. package/bin/tracetractor +0 -1
  6. package/index.js +12 -18
  7. package/lib/agent.js +108 -111
  8. package/lib/aggregators/base-aggregator.js +1 -1
  9. package/lib/aggregators/event-aggregator.js +6 -6
  10. package/lib/attributes.js +12 -13
  11. package/lib/collector/api.js +32 -42
  12. package/lib/collector/facts.js +67 -65
  13. package/lib/collector/http-agents.js +30 -27
  14. package/lib/collector/parse-response.js +1 -2
  15. package/lib/collector/remote-method.js +43 -36
  16. package/lib/collector/serverless.js +13 -18
  17. package/lib/collector/ssl/certificates.js +1056 -1056
  18. package/lib/config/attribute-filter.js +90 -82
  19. package/lib/config/default.js +30 -18
  20. package/lib/config/env.js +17 -12
  21. package/lib/config/harvest-config-validator.js +1 -1
  22. package/lib/config/index.js +160 -177
  23. package/lib/config/merge-server-config.js +7 -5
  24. package/lib/custom-events/custom-event-aggregator.js +1 -1
  25. package/lib/db/parse-sql.js +6 -9
  26. package/lib/db/parsed-statement.js +6 -13
  27. package/lib/db/query-parsers/sql.js +6 -9
  28. package/lib/db/query-sample.js +7 -3
  29. package/lib/db/query-trace-aggregator.js +12 -12
  30. package/lib/db/utils.js +1 -1
  31. package/lib/environment.js +173 -138
  32. package/lib/errors/error-collector.js +18 -31
  33. package/lib/errors/error-event-aggregator.js +1 -1
  34. package/lib/errors/error-trace-aggregator.js +2 -3
  35. package/lib/errors/helper.js +21 -30
  36. package/lib/errors/index.js +16 -28
  37. package/lib/feature_flags.js +5 -8
  38. package/lib/grpc/connection/states.js +6 -6
  39. package/lib/grpc/connection.js +35 -46
  40. package/lib/header-attributes.js +49 -53
  41. package/lib/instrumentation/amqplib.js +8 -17
  42. package/lib/instrumentation/bluebird.js +61 -20
  43. package/lib/instrumentation/cassandra-driver.js +2 -2
  44. package/lib/instrumentation/connect.js +4 -3
  45. package/lib/instrumentation/core/async_hooks.js +11 -4
  46. package/lib/instrumentation/core/child_process.js +20 -28
  47. package/lib/instrumentation/core/crypto.js +1 -7
  48. package/lib/instrumentation/core/dns.js +3 -7
  49. package/lib/instrumentation/core/domain.js +2 -8
  50. package/lib/instrumentation/core/fs.js +22 -37
  51. package/lib/instrumentation/core/globals.js +3 -7
  52. package/lib/instrumentation/core/http-outbound.js +15 -40
  53. package/lib/instrumentation/core/http.js +29 -63
  54. package/lib/instrumentation/core/inspector.js +6 -10
  55. package/lib/instrumentation/core/net.js +3 -1
  56. package/lib/instrumentation/core/timers.js +17 -24
  57. package/lib/instrumentation/core/zlib.js +2 -10
  58. package/lib/instrumentation/express.js +4 -2
  59. package/lib/instrumentation/fastify/spec-builders.js +5 -0
  60. package/lib/instrumentation/fastify.js +37 -10
  61. package/lib/instrumentation/hapi/hapi-17.js +9 -10
  62. package/lib/instrumentation/hapi.js +15 -15
  63. package/lib/instrumentation/ioredis.js +1 -2
  64. package/lib/instrumentation/memcached.js +39 -43
  65. package/lib/instrumentation/mongodb/common.js +218 -0
  66. package/lib/instrumentation/mongodb/constants.js +87 -0
  67. package/lib/instrumentation/mongodb/v2-mongo.js +110 -0
  68. package/lib/instrumentation/mongodb/v3-mongo.js +80 -0
  69. package/lib/instrumentation/mongodb/v4-mongo.js +90 -0
  70. package/lib/instrumentation/mongodb.js +20 -312
  71. package/lib/instrumentation/mysql.js +33 -26
  72. package/lib/instrumentation/oracle.js +10 -14
  73. package/lib/instrumentation/pg.js +30 -21
  74. package/lib/instrumentation/promise.js +20 -17
  75. package/lib/instrumentation/redis.js +30 -30
  76. package/lib/instrumentation/when.js +9 -1
  77. package/lib/instrumentations.js +24 -24
  78. package/lib/logger.js +1 -1
  79. package/lib/metrics/index.js +37 -17
  80. package/lib/metrics/mapper.js +9 -9
  81. package/lib/metrics/metric-aggregator.js +5 -10
  82. package/lib/metrics/names.js +8 -7
  83. package/lib/metrics/normalizer/rule.js +6 -7
  84. package/lib/metrics/normalizer/tx_segment.js +17 -13
  85. package/lib/metrics/normalizer.js +30 -33
  86. package/lib/metrics/recorders/custom.js +3 -1
  87. package/lib/metrics/recorders/distributed-trace.js +3 -18
  88. package/lib/metrics/recorders/generic.js +3 -2
  89. package/lib/metrics/recorders/http.js +4 -6
  90. package/lib/metrics/recorders/http_external.js +1 -3
  91. package/lib/metrics/recorders/message-transaction.js +2 -12
  92. package/lib/metrics/recorders/other.js +2 -12
  93. package/lib/parse-proc-cpuinfo.js +11 -16
  94. package/lib/parse-proc-meminfo.js +5 -3
  95. package/lib/prioritized-attributes.js +12 -17
  96. package/lib/priority-queue.js +1 -1
  97. package/lib/proxy/grpc.js +1 -1
  98. package/lib/reservoir.js +9 -3
  99. package/lib/sampler.js +12 -13
  100. package/lib/serverless/api-gateway.js +3 -3
  101. package/lib/serverless/aws-lambda.js +28 -37
  102. package/lib/shim/conglomerate-shim.js +4 -4
  103. package/lib/shim/datastore-shim.js +29 -38
  104. package/lib/shim/index.js +8 -9
  105. package/lib/shim/message-shim.js +111 -113
  106. package/lib/shim/promise-shim.js +18 -13
  107. package/lib/shim/shim.js +72 -66
  108. package/lib/shim/specs/index.js +18 -19
  109. package/lib/shim/transaction-shim.js +26 -36
  110. package/lib/shim/webframework-shim.js +25 -35
  111. package/lib/shimmer.js +184 -166
  112. package/lib/spans/create-span-event-aggregator.js +24 -44
  113. package/lib/spans/span-context.js +4 -10
  114. package/lib/spans/span-event-aggregator.js +68 -13
  115. package/lib/spans/span-event.js +5 -7
  116. package/lib/spans/span-streamer.js +10 -18
  117. package/lib/spans/streaming-span-event-aggregator.js +1 -1
  118. package/lib/spans/streaming-span-event.js +4 -4
  119. package/lib/stats/apdex.js +5 -11
  120. package/lib/stats/index.js +12 -17
  121. package/lib/system-info.js +7 -3
  122. package/lib/timer.js +30 -16
  123. package/lib/transaction/dt-payload.js +1 -1
  124. package/lib/transaction/handle.js +19 -19
  125. package/lib/transaction/index.js +94 -112
  126. package/lib/transaction/name-state.js +5 -6
  127. package/lib/transaction/trace/aggregator.js +78 -73
  128. package/lib/transaction/trace/exclusive-time-calculator.js +5 -9
  129. package/lib/transaction/trace/index.js +26 -24
  130. package/lib/transaction/trace/segment.js +39 -56
  131. package/lib/transaction/tracecontext.js +37 -45
  132. package/lib/transaction/tracer/index.js +79 -44
  133. package/lib/transaction/transaction-event-aggregator.js +29 -31
  134. package/lib/uninstrumented.js +4 -5
  135. package/lib/util/attribute-types.js +1 -5
  136. package/lib/util/byte-limit.js +0 -1
  137. package/lib/util/cat.js +5 -13
  138. package/lib/util/codec.js +8 -4
  139. package/lib/util/deep-equal.js +48 -18
  140. package/lib/util/flatten.js +5 -2
  141. package/lib/util/hashes.js +2 -2
  142. package/lib/util/label-parser.js +7 -13
  143. package/lib/util/logger.js +31 -13
  144. package/lib/util/process-version.js +1 -1
  145. package/lib/util/properties.js +1 -1
  146. package/lib/util/sql/obfuscate.js +7 -17
  147. package/lib/util/stream-sink.js +2 -3
  148. package/lib/util/urltils.js +9 -13
  149. package/lib/utilization/aws-info.js +2 -3
  150. package/lib/utilization/azure-info.js +32 -30
  151. package/lib/utilization/common.js +5 -4
  152. package/lib/utilization/docker-info.js +4 -6
  153. package/lib/utilization/gcp-info.js +36 -35
  154. package/lib/utilization/index.js +1 -1
  155. package/lib/utilization/kubernetes-info.js +2 -2
  156. package/lib/utilization/pcf-info.js +4 -4
  157. package/package.json +32 -18
  158. package/stub_api.js +8 -6
@@ -6,6 +6,9 @@
6
6
  'use strict'
7
7
 
8
8
  const semver = require('semver')
9
+ const instrument = require('./mongodb/v2-mongo')
10
+ const instrumentV3 = require('./mongodb/v3-mongo')
11
+ const instrumentV4 = require('./mongodb/v4-mongo')
9
12
 
10
13
  // XXX: When this instrumentation is modularized, update this thread
11
14
  // with a cautionary note:
@@ -15,325 +18,30 @@ const semver = require('semver')
15
18
  // snippet. The snippet will break once this file is moved from this
16
19
  // location.
17
20
 
18
- // legacy endpoint enumerations
19
- const DB_OPS = [
20
- 'addUser',
21
- 'authenticate',
22
- 'collection',
23
- 'collectionNames',
24
- 'collections',
25
- 'command',
26
- 'createCollection',
27
- 'createIndex',
28
- 'cursorInfo',
29
- 'dereference',
30
- 'dropCollection',
31
- 'dropDatabase',
32
- 'dropIndex',
33
- 'ensureIndex',
34
- 'eval',
35
- 'executeDbAdminCommand',
36
- 'indexInformation',
37
- 'logout',
38
- 'open',
39
- 'reIndex',
40
- 'removeUser',
41
- 'renameCollection',
42
- 'stats',
43
- '_executeInsertCommand',
44
- '_executeQueryCommand'
45
- ]
46
-
47
- const COLLECTION_OPS = [
48
- 'aggregate',
49
- 'bulkWrite',
50
- 'count',
51
- 'createIndex',
52
- 'deleteMany',
53
- 'deleteOne',
54
- 'distinct',
55
- 'drop',
56
- 'dropAllIndexes',
57
- 'dropIndex',
58
- 'ensureIndex',
59
- 'findAndModify',
60
- 'findAndRemove',
61
- 'findOne',
62
- 'findOneAndDelete',
63
- 'findOneAndReplace',
64
- 'findOneAndUpdate',
65
- 'geoHaystackSearch',
66
- 'geoNear',
67
- 'group',
68
- 'indexes',
69
- 'indexExists',
70
- 'indexInformation',
71
- 'insert',
72
- 'insertMany',
73
- 'insertOne',
74
- 'isCapped',
75
- 'mapReduce',
76
- 'options',
77
- 'parallelCollectionScan',
78
- 'reIndex',
79
- 'remove',
80
- 'rename',
81
- 'replaceOne',
82
- 'save',
83
- 'stats',
84
- 'update',
85
- 'updateMany',
86
- 'updateOne'
87
- ]
88
-
89
- const GRID_OPS = [
90
- 'put',
91
- 'get',
92
- 'delete'
93
- ]
94
-
95
- const CURSOR_OPS = [
96
- 'nextObject',
97
- 'next',
98
- 'toArray',
99
- 'count',
100
- 'explain'
101
- ]
102
-
103
21
  module.exports = initialize
104
22
 
23
+ /**
24
+ * Registers the query parser, and relevant instrumentation
25
+ * based on version of mongodb
26
+ *
27
+ * @param {Agent} agent
28
+ * @param {Object} mongodb resolved package
29
+ * @param {string} moduleName name of module
30
+ * @param {Shim} shim
31
+ */
105
32
  function initialize(agent, mongodb, moduleName, shim) {
106
- if (!mongodb) return
33
+ if (!mongodb) {
34
+ return
35
+ }
107
36
 
108
37
  shim.setDatastore(shim.MONGODB)
109
- shim.setParser(function mongoQueryParser(operation) {
110
- let collection = this.collectionName || 'unknown'
111
- if (this.collection && this.collection.collectionName) {
112
- collection = this.collection.collectionName
113
- } else if (this.s && this.s.name) {
114
- collection = this.s.name
115
- } else if (this.ns) {
116
- collection = this.ns.split(/\./)[1] || collection
117
- }
118
-
119
- return {operation, collection}
120
- })
121
38
 
122
39
  const mongoVersion = shim.require('./package.json').version
123
- if (semver.satisfies(mongoVersion, '>=3.0.6') && mongodb.instrument) {
124
- instrument306(shim, mongodb)
125
- } else if (mongodb.instrument) {
126
- instrumentInstrument(shim, mongodb)
40
+ if (semver.satisfies(mongoVersion, '>=4.0.0')) {
41
+ instrumentV4(shim, mongodb)
42
+ } else if (semver.satisfies(mongoVersion, '>=3.0.6')) {
43
+ instrumentV3(shim, mongodb)
127
44
  } else {
128
- instrumentLegacy(shim, mongodb)
129
- }
130
- }
131
-
132
- function instrument306(shim, mongodb) {
133
- const instrumenter = mongodb.instrument(Object.create(null), () => {})
134
- captureAttributesOnStarted(shim, instrumenter)
135
- instrumentLegacy(shim, mongodb)
136
-
137
- if (shim.isFunction(instrumenter.uninstrument)) {
138
- shim.agent.once('unload', function uninstrumentMongo() {
139
- instrumenter.uninstrument()
140
- })
141
- }
142
- }
143
-
144
- function instrumentInstrument(shim, mongodb) {
145
- const recordDesc = {
146
- 'Gridstore': {isQuery: false, makeDesc: function makeGridDesc(opName) {
147
- return {name:'GridFS-' + opName, callback: shim.LAST}
148
- }},
149
- 'OrderedBulkOperation': {isQuery: true, makeDesc: makeQueryDescFunc},
150
- 'UnorderedBulkOperation': {isQuery: true, makeDesc: makeQueryDescFunc},
151
- 'CommandCursor': {isQuery: true, makeDesc: makeQueryDescFunc},
152
- 'AggregationCursor': {isQuery: true, makeDesc: makeQueryDescFunc},
153
- 'Cursor': {isQuery: true, makeDesc: makeQueryDescFunc},
154
- 'Collection': {isQuery: true, makeDesc: makeQueryDescFunc},
155
- 'Db': {isQuery: false, makeDesc: function makeDbDesc() {
156
- return {callback: shim.LAST}
157
- }}
158
- }
159
-
160
- // instrument using the apm api
161
- const instrumenter = mongodb.instrument(Object.create(null), instrumentModules)
162
- captureAttributesOnStarted(shim, instrumenter)
163
-
164
- function instrumentModules(err, instrumentations) {
165
- if (err) {
166
- shim.logger
167
- .trace('Unable to instrument mongo using the apm api due to error: %s', err)
168
- // fallback to legacy instrumentation?
169
- return
170
- }
171
- instrumentations.forEach(instrumentModule)
172
- }
173
-
174
- function instrumentModule(module) {
175
- var object = module.obj
176
- var instrumentations = module.instrumentations
177
- for (var i = 0; i < instrumentations.length; i++) {
178
- applyInstrumentation(module.name, object, instrumentations[i])
179
- }
180
- }
181
-
182
- function applyInstrumentation(objectName, object, instrumentation) {
183
- var methods = instrumentation.methods
184
- var methodOptions = instrumentation.options
185
- if (methodOptions.callback) {
186
- for (var j = 0; j < methods.length; j++) {
187
- var method = methods[j]
188
-
189
- var isQuery = recordDesc[objectName].isQuery
190
- var makeDescFunc = recordDesc[objectName].makeDesc
191
- var proto = object.prototype
192
- if (isQuery) {
193
- shim.recordQuery(proto, method, makeDescFunc(shim, method))
194
- } else if (isQuery === false) { // could be unset
195
- shim.recordOperation(proto, method, makeDescFunc(shim, method))
196
- } else {
197
- shim.logger.trace('No wrapping method found for %s', objectName)
198
- }
199
- }
200
- }
201
-
202
- // the cursor object implements Readable stream and internally calls nextObject on
203
- // each read, in which case we do not want to record each nextObject() call
204
- if (/Cursor$/.test(objectName)) {
205
- shim.recordOperation(object.prototype, 'pipe')
206
- }
207
- }
208
- }
209
-
210
- function captureAttributesOnStarted(shim, instrumenter) {
211
- instrumenter.on('started', function onMongoEventStarted(evnt) {
212
- // This assumes that this `started` event is fired _after_ our wrapper
213
- // starts and creates the segment. We perform a check of the segment name
214
- // out of an excess of caution.
215
- const connId = evnt.connectionId
216
- if (connId) {
217
- // Mongo sticks the path to the domain socket in the "host" slot, but we
218
- // want it in the "port", so if we have a domain socket we need to change
219
- // the order of our parameters.
220
- if (typeof connId === 'string') {
221
- const parts = connId.split(':')
222
- if (parts.length && parts[0][0] === '/') {
223
- shim.captureInstanceAttributes('localhost', parts[0], evnt.databaseName)
224
- } else {
225
- shim.captureInstanceAttributes(parts[0], parts[1], evnt.databaseName)
226
- }
227
- } else if (connId.domainSocket) {
228
- shim.captureInstanceAttributes('localhost', connId.host, evnt.databaseName)
229
- } else {
230
- shim.captureInstanceAttributes(connId.host, connId.port, evnt.databaseName)
231
- }
232
- }
233
- })
234
- }
235
-
236
- function instrumentLegacy(shim, mongodb) {
237
- instrumentCursor(mongodb.Cursor)
238
- instrumentCursor(shim.require('./lib/aggregation_cursor'))
239
- instrumentCursor(shim.require('./lib/command_cursor'))
240
-
241
- if (mongodb.Collection && mongodb.Collection.prototype) {
242
- const proto = mongodb.Collection.prototype
243
- for (let i = 0; i < COLLECTION_OPS.length; i++) {
244
- shim.recordQuery(
245
- proto,
246
- COLLECTION_OPS[i],
247
- makeQueryDescFunc(shim, COLLECTION_OPS[i])
248
- )
249
- }
250
- }
251
-
252
- if (mongodb.Grid && mongodb.Grid.prototype) {
253
- const proto = mongodb.Grid.prototype
254
- for (let i = 0; i < CURSOR_OPS.length; i++) {
255
- shim.recordOperation(proto, GRID_OPS[i],
256
- {name:'GridFS-' + GRID_OPS[i], callback: shim.LAST})
257
- }
258
- }
259
-
260
- if (mongodb.Db && mongodb.Db.prototype) {
261
- const proto = mongodb.Db.prototype
262
- shim.recordOperation(proto, DB_OPS, {callback: shim.LAST})
263
- shim.recordOperation(mongodb.Db, 'connect', {callback: shim.LAST})
264
- }
265
-
266
- function instrumentCursor(Cursor) {
267
- if (Cursor && Cursor.prototype) {
268
- const proto = Cursor.prototype
269
- for (let i = 0; i < CURSOR_OPS.length; i++) {
270
- shim.recordQuery(proto, CURSOR_OPS[i], makeQueryDescFunc(shim, CURSOR_OPS[i]))
271
- }
272
-
273
- shim.recordQuery(proto, 'each', makeQueryDescFunc(shim, 'each'))
274
- shim.recordOperation(proto, 'pipe')
275
- }
276
- }
277
- }
278
-
279
- function makeQueryDescFunc(shim, methodName) {
280
- if (methodName === 'each') {
281
- return function eachDescFunc() {
282
- const parameters = getInstanceAttributeParameters(shim, this)
283
- return {query: methodName, parameters, rowCallback: shim.LAST}
284
- }
285
- }
286
-
287
- return function queryDescFunc() {
288
- // segment name does not actually use query string
289
- // method name is set as query so the query parser has access to the op name
290
- const parameters = getInstanceAttributeParameters(shim, this)
291
- return {query: methodName, parameters, promise: true, callback: shim.LAST}
292
- }
293
- }
294
-
295
- function getInstanceAttributeParameters(shim, obj) {
296
- if (obj.db && obj.db.serverConfig) {
297
- shim.logger.trace('Adding datastore instance attributes from obj.db.serverConfig')
298
- const serverConfig = obj.db.serverConfig
299
- const db = serverConfig.db || serverConfig.dbInstance
300
- return doCapture(serverConfig, db && db.databaseName)
301
- } else if (obj.s && obj.s.db && obj.s.topology) {
302
- shim.logger.trace(
303
- 'Adding datastore instance attributes from obj.s.db + obj.s.topology'
304
- )
305
- const databaseName = obj.s.db.databaseName || null
306
- const topology = obj.s.topology
307
- if (topology.s && topology.s.options) {
308
- return doCapture(topology.s.options, databaseName)
309
- }
310
- }
311
-
312
- shim.logger.trace('Could not find datastore instance attributes.')
313
- return {
314
- host: null,
315
- port_path_or_id: null,
316
- database_name: null
317
- }
318
-
319
- function doCapture(conf, database) {
320
- let host = conf.host
321
- let port = conf.port
322
-
323
- // If using a domain socket, mongo stores the path as the host name, but we
324
- // pass it through the port value.
325
- if (
326
- (conf.socketOptions && conf.socketOptions.domainSocket) ||
327
- /\.sock$/.test(host)
328
- ) {
329
- port = host
330
- host = 'localhost'
331
- }
332
-
333
- return {
334
- host: host,
335
- port_path_or_id: port,
336
- database_name: database
337
- }
45
+ instrument(shim, mongodb)
338
46
  }
339
47
  }
@@ -8,7 +8,6 @@
8
8
  var dbutils = require('../db/utils')
9
9
  var properties = require('../util/properties')
10
10
 
11
-
12
11
  module.exports = function initialize(agent, mysql, moduleName, shim) {
13
12
  shim.setDatastore(shim.MYSQL)
14
13
  shim.__wrappedPoolConnection = false
@@ -50,16 +49,15 @@ module.exports = function initialize(agent, mysql, moduleName, shim) {
50
49
  }
51
50
 
52
51
  function wrapGetConnection(shim, connectable) {
53
- if (
54
- !connectable ||
55
- !connectable.getConnection ||
56
- shim.isWrapped(connectable.getConnection)
57
- ) {
58
- shim.logger.trace({
59
- connectable: !!connectable,
60
- getConnection: !!(connectable && connectable.getConnection),
61
- isWrapped: !!(connectable && shim.isWrapped(connectable.getConnection))
62
- }, 'Not wrapping getConnection')
52
+ if (!connectable || !connectable.getConnection || shim.isWrapped(connectable.getConnection)) {
53
+ shim.logger.trace(
54
+ {
55
+ connectable: !!connectable,
56
+ getConnection: !!(connectable && connectable.getConnection),
57
+ isWrapped: !!(connectable && shim.isWrapped(connectable.getConnection))
58
+ },
59
+ 'Not wrapping getConnection'
60
+ )
63
61
  return false
64
62
  }
65
63
 
@@ -70,9 +68,12 @@ function wrapGetConnection(shim, connectable) {
70
68
  var cbIdx = args.length - 1
71
69
 
72
70
  if (shim.isFunction(args[cbIdx]) && !shim.isWrapped(args[cbIdx])) {
73
- shim.logger.trace({
74
- hasSegment: !!shim.getSegment()
75
- }, 'Wrapping callback with segment')
71
+ shim.logger.trace(
72
+ {
73
+ hasSegment: !!shim.getSegment()
74
+ },
75
+ 'Wrapping callback with segment'
76
+ )
76
77
  var cb = args[cbIdx]
77
78
  if (!shim.__wrappedPoolConnection) {
78
79
  cb = shim.wrap(cb, wrapGetConnectionCallback)
@@ -97,7 +98,7 @@ function wrapGetConnectionCallback(shim, cb) {
97
98
  }
98
99
  } catch (_err) {
99
100
  shim.logger.debug(
100
- {error: _err},
101
+ { error: _err },
101
102
  'Attempt to wrap PoolConnection#query resulted in thrown error'
102
103
  )
103
104
  }
@@ -107,11 +108,14 @@ function wrapGetConnectionCallback(shim, cb) {
107
108
 
108
109
  function wrapQueriable(shim, queriable, isPoolQuery) {
109
110
  if (!queriable || !queriable.query || shim.isWrapped(queriable.query)) {
110
- shim.logger.debug({
111
- queriable: !!queriable,
112
- query: !!(queriable && queriable.query),
113
- isWrapped: !!(queriable && shim.isWrapped(queriable.query))
114
- }, 'Not wrappying queriable')
111
+ shim.logger.debug(
112
+ {
113
+ queriable: !!queriable,
114
+ query: !!(queriable && queriable.query),
115
+ isWrapped: !!(queriable && shim.isWrapped(queriable.query))
116
+ },
117
+ 'Not wrappying queriable'
118
+ )
115
119
  return false
116
120
  }
117
121
 
@@ -169,11 +173,14 @@ function describeQuery(shim, queryFn, fnName, args) {
169
173
  // Pull out instance attributes.
170
174
  var parameters = getInstanceParameters(shim, this, extractedArgs.query)
171
175
 
172
- shim.logger.trace({
173
- query: !!extractedArgs.query,
174
- callback: !!extractedArgs.callback,
175
- parameters: !!parameters
176
- }, 'Query segment descriptor')
176
+ shim.logger.trace(
177
+ {
178
+ query: !!extractedArgs.query,
179
+ callback: !!extractedArgs.callback,
180
+ parameters: !!parameters
181
+ },
182
+ 'Query segment descriptor'
183
+ )
177
184
 
178
185
  return {
179
186
  stream: true,
@@ -197,7 +204,7 @@ function describePoolQuery(shim, queryFn, fnName, args) {
197
204
  }
198
205
 
199
206
  function getInstanceParameters(shim, queryable, query) {
200
- var parameters = {host: null, port_path_or_id: null, database_name: null}
207
+ var parameters = { host: null, port_path_or_id: null, database_name: null }
201
208
  var conf = queryable.config
202
209
  conf = (conf && conf.connectionConfig) || conf
203
210
  var databaseName = queryable.__NR_databaseName || null
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- var logger = require('../logger').child({component: 'oracle'})
8
+ var logger = require('../logger').child({ component: 'oracle' })
9
9
  var shimmer = require('../shimmer')
10
10
  var parseSql = require('../db/parse-sql')
11
11
  var ORACLE = require('../metrics/names').ORACLE
@@ -16,16 +16,14 @@ module.exports = function initialize(agent, oracle) {
16
16
 
17
17
  logger.trace('wrapping oracle.connect and oracle.connectSync')
18
18
 
19
- shimmer.wrapMethod(oracle, 'Oracle', 'connect', function cb_wrapMethod(connect) {
19
+ shimmer.wrapMethod(oracle, 'Oracle', 'connect', function wrapMethod(connect) {
20
20
  return function wrappedConnect(connectData, cb) {
21
- return connect.call(
22
- this,
23
- connectData,
24
- tracer.bindFunction(wrapConnection)
25
- )
21
+ return connect.call(this, connectData, tracer.bindFunction(wrapConnection))
26
22
 
27
23
  function wrapConnection(err, connection) {
28
- if (!err) ensureConnectionWrapped(connection)
24
+ if (!err) {
25
+ ensureConnectionWrapped(connection)
26
+ }
29
27
  return cb(err, connection)
30
28
  }
31
29
  }
@@ -41,7 +39,9 @@ module.exports = function initialize(agent, oracle) {
41
39
 
42
40
  function ensureConnectionWrapped(connection) {
43
41
  // return early in case called from an async connect after wrapping
44
- if (wrapped) return
42
+ if (wrapped) {
43
+ return
44
+ }
45
45
  logger.trace('wrapping oracle connection prototype')
46
46
  wrapped = true
47
47
 
@@ -78,11 +78,7 @@ function wrapConnectionExecute(connection, tracer) {
78
78
  var operation = ps.operation
79
79
 
80
80
  segment.name = ORACLE.STATEMENT + collection + '/Connection.execute/' + operation
81
- logger.trace(
82
- 'capturing oracle query. collection: %s, Operation: %s',
83
- collection,
84
- operation
85
- )
81
+ logger.trace('capturing oracle query. collection: %s, Operation: %s', collection, operation)
86
82
 
87
83
  segment.transaction.addRecorder(ps.recordMetrics.bind(ps, segment))
88
84
  args[2] = bind(args[2])
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const semver = require('semver')
9
+
8
10
  function getQuery(shim, original, name, args) {
9
11
  var config = args[0]
10
12
  var statement
@@ -20,6 +22,8 @@ function getQuery(shim, original, name, args) {
20
22
  }
21
23
 
22
24
  module.exports = function initialize(agent, pgsql, moduleName, shim) {
25
+ const pgVersion = shim.require('./package.json').version
26
+
23
27
  shim.setDatastore(shim.POSTGRES)
24
28
  // allows for native wrapping to not happen if not necessary
25
29
  // when env var is true
@@ -28,6 +32,29 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
28
32
  return instrumentPGNative(pgsql)
29
33
  }
30
34
 
35
+ function wrapJSClientQuery(shim, _, __, queryArgs) {
36
+ // As of pg v7.0.0, Client.query returns a Promise from an async call.
37
+ // pg supports event based Client.query when a Query object is passed in,
38
+ // and works similarly in pg version <7.0.0
39
+ if (semver.satisfies(pgVersion, '>=7.0.0') && typeof queryArgs[0] === 'string') {
40
+ return {
41
+ callback: shim.LAST,
42
+ query: getQuery,
43
+ promise: true,
44
+ parameters: getInstanceParameters(shim, this),
45
+ internal: false
46
+ }
47
+ }
48
+
49
+ return {
50
+ callback: shim.LAST,
51
+ query: getQuery,
52
+ stream: 'row',
53
+ parameters: getInstanceParameters(shim, this),
54
+ internal: false
55
+ }
56
+ }
57
+
31
58
  // wrapping for native
32
59
  function instrumentPGNative(pg) {
33
60
  shim.wrapReturn(pg, 'Client', clientFactoryWrapper)
@@ -41,7 +68,7 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
41
68
  // constructor and pg.pools so we can check against pg.pools to only
42
69
  // instrument pg.Pool on v6 and later.
43
70
  if (!pg.pools) {
44
- shim.wrapClass(pg, 'Pool', {post: poolPostConstructor, es6: true})
71
+ shim.wrapClass(pg, 'Pool', { post: poolPostConstructor, es6: true })
45
72
  }
46
73
  }
47
74
 
@@ -56,13 +83,7 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
56
83
  }
57
84
 
58
85
  function clientPostConstructor(shim) {
59
- shim.recordQuery(this, 'query', {
60
- callback: shim.LAST,
61
- query: getQuery,
62
- stream: 'row',
63
- parameters: getInstanceParameters(shim, this),
64
- internal: false
65
- })
86
+ shim.recordQuery(this, 'query', wrapJSClientQuery)
66
87
 
67
88
  shim.record(this, 'connect', function pgConnectNamer() {
68
89
  return {
@@ -90,19 +111,7 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
90
111
  }
91
112
 
92
113
  // wrapping for JS
93
- shim.recordQuery(
94
- pgsql && pgsql.Client && pgsql.Client.prototype,
95
- 'query',
96
- function wrapJSClientQuery(shim) {
97
- return {
98
- callback: shim.LAST,
99
- query: getQuery,
100
- stream: 'row',
101
- parameters: getInstanceParameters(shim, this),
102
- internal: false
103
- }
104
- }
105
- )
114
+ shim.recordQuery(pgsql && pgsql.Client && pgsql.Client.prototype, 'query', wrapJSClientQuery)
106
115
  }
107
116
 
108
117
  function getInstanceParameters(shim, client) {