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,7 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  var genericRecorder = require('../metrics/recorders/generic')
9
- var logger = require('../logger.js').child({component: 'WebFrameworkShim'})
9
+ var logger = require('../logger.js').child({ component: 'WebFrameworkShim' })
10
10
  var metrics = require('../metrics/names')
11
11
  var TransactionShim = require('./transaction-shim')
12
12
  var Shim = require('./shim')
@@ -14,7 +14,6 @@ var specs = require('./specs')
14
14
  var urltils = require('../util/urltils')
15
15
  var util = require('util')
16
16
 
17
-
18
17
  /**
19
18
  * An enumeration of well-known web frameworks so that new instrumentations can
20
19
  * use the same names we already use for first-party instrumentation.
@@ -37,12 +36,12 @@ var FRAMEWORK_NAMES = {
37
36
  }
38
37
 
39
38
  var MIDDLEWARE_TYPE_DETAILS = {
40
- APPLICATION: {name: 'Mounted App: ', path: true, record: false},
41
- ERRORWARE: {name: '', path: false, record: true},
42
- MIDDLEWARE: {name: '', path: false, record: true},
43
- PARAMWARE: {name: '', path: false, record: true},
44
- ROUTE: {name: 'Route Path: ', path: true, record: false},
45
- ROUTER: {name: 'Router: ', path: true, record: false}
39
+ APPLICATION: { name: 'Mounted App: ', path: true, record: false },
40
+ ERRORWARE: { name: '', path: false, record: true },
41
+ MIDDLEWARE: { name: '', path: false, record: true },
42
+ PARAMWARE: { name: '', path: false, record: true },
43
+ ROUTE: { name: 'Route Path: ', path: true, record: false },
44
+ ROUTER: { name: 'Router: ', path: true, record: false }
46
45
  }
47
46
 
48
47
  var MIDDLEWARE_TYPE_NAMES = {
@@ -61,7 +60,6 @@ var MIDDLEWARE_TYPE_NAMES = {
61
60
  */
62
61
  var TRANSACTION_INFO_KEY = '__NR_transactionInfo'
63
62
 
64
-
65
63
  /**
66
64
  * Constructs a shim associated with the given agent instance, specialized for
67
65
  * instrumenting web frameworks.
@@ -89,7 +87,7 @@ var TRANSACTION_INFO_KEY = '__NR_transactionInfo'
89
87
  */
90
88
  function WebFrameworkShim(agent, moduleName, resolvedName, frameworkId) {
91
89
  TransactionShim.call(this, agent, moduleName, resolvedName)
92
- this._logger = logger.child({module: moduleName})
90
+ this._logger = logger.child({ module: moduleName })
93
91
  if (frameworkId) {
94
92
  this.setFramework(frameworkId)
95
93
  }
@@ -326,8 +324,8 @@ function setFramework(framework) {
326
324
  }
327
325
  this.agent.environment.setFramework(framework)
328
326
 
329
- this._logger = this._logger.child({framework: framework})
330
- this.logger.trace({metrics: this._metrics}, 'Framework metric names set')
327
+ this._logger = this._logger.child({ framework: framework })
328
+ this.logger.trace({ metrics: this._metrics }, 'Framework metric names set')
331
329
  }
332
330
 
333
331
  /**
@@ -343,12 +341,7 @@ function setTransactionUri(uri) {
343
341
  return
344
342
  }
345
343
 
346
- tx.nameState.setName(
347
- this._metrics.FRAMEWORK,
348
- tx.verb,
349
- metrics.ACTION_DELIMITER,
350
- uri
351
- )
344
+ tx.nameState.setName(this._metrics.FRAMEWORK, tx.verb, metrics.ACTION_DELIMITER, uri)
352
345
  }
353
346
 
354
347
  /**
@@ -388,10 +381,7 @@ function recordRender(nodule, properties, spec) {
388
381
  return this.record(nodule, properties, function renderRecorder(shim, fn, name, args) {
389
382
  var viewIdx = shim.normalizeIndex(args.length, spec.view)
390
383
  if (viewIdx === null) {
391
- shim.logger.debug(
392
- 'Invalid spec.view (%d vs %d), not recording.',
393
- spec.view, args.length
394
- )
384
+ shim.logger.debug('Invalid spec.view (%d vs %d), not recording.', spec.view, args.length)
395
385
  return null
396
386
  }
397
387
 
@@ -441,7 +431,7 @@ function wrapMiddlewareMounter(nodule, properties, spec) {
441
431
  }
442
432
  if (this.isFunction(spec)) {
443
433
  // wrapMiddlewareMounter(nodule [, properties], wrapper)
444
- spec = {wrapper: spec}
434
+ spec = { wrapper: spec }
445
435
  }
446
436
 
447
437
  spec = this.setDefaults(spec, {
@@ -823,9 +813,7 @@ function _recordMiddleware(shim, middleware, spec) {
823
813
 
824
814
  return shim.record(
825
815
  middleware,
826
- spec.promise
827
- ? middlewareWithPromiseRecorder
828
- : middlewareWithCallbackRecorder
816
+ spec.promise ? middlewareWithPromiseRecorder : middlewareWithCallbackRecorder
829
817
  )
830
818
 
831
819
  // TODO: let's please break these out
@@ -839,9 +827,10 @@ function _recordMiddleware(shim, middleware, spec) {
839
827
  var txInfo = _getTransactionInfo(shim, req)
840
828
  if (!txInfo || !txInfo.transaction) {
841
829
  shim.logger.debug(
842
- {txInfo: txInfo},
830
+ { txInfo: txInfo },
843
831
  'Could not get transaction info in %s (%s)',
844
- route, fnName
832
+ route,
833
+ fnName
845
834
  )
846
835
  return null
847
836
  }
@@ -850,7 +839,8 @@ function _recordMiddleware(shim, middleware, spec) {
850
839
 
851
840
  // Copy over route parameters onto the transaction root.
852
841
  var params = shim.agent.config.high_security
853
- ? null : spec.params.call(this, shim, fn, fnName, args, req)
842
+ ? null
843
+ : spec.params.call(this, shim, fn, fnName, args, req)
854
844
 
855
845
  // Wrap up `next` and push on our name state if we find it. We only want to
856
846
  // push the name state if there is a next so that we can safely remove it
@@ -929,9 +919,10 @@ function _recordMiddleware(shim, middleware, spec) {
929
919
  var txInfo = _getTransactionInfo(shim, req)
930
920
  if (!txInfo || !txInfo.transaction) {
931
921
  shim.logger.debug(
932
- {txInfo: txInfo},
922
+ { txInfo: txInfo },
933
923
  'Could not get transaction info in %s (%s)',
934
- route, fnName
924
+ route,
925
+ fnName
935
926
  )
936
927
  return null
937
928
  }
@@ -940,7 +931,8 @@ function _recordMiddleware(shim, middleware, spec) {
940
931
 
941
932
  // Copy over route parameters onto the transaction root.
942
933
  var params = shim.agent.config.high_security
943
- ? null : spec.params.call(this, shim, fn, fnName, args, req)
934
+ ? null
935
+ : spec.params.call(this, shim, fn, fnName, args, req)
944
936
 
945
937
  // Append this middleware's mount point and possibly construct a recorder.
946
938
  if (spec.appendPath) {
@@ -1171,9 +1163,7 @@ function _isError(shim, err) {
1171
1163
  * The spec object the values are coming from
1172
1164
  */
1173
1165
  function _copyExpectedSpecParameters(destination, source) {
1174
- var keys = [
1175
- 'matchArity'
1176
- ]
1166
+ var keys = ['matchArity']
1177
1167
 
1178
1168
  for (var i = 0; i < keys.length; ++i) {
1179
1169
  var key = keys[i]
package/lib/shimmer.js CHANGED
@@ -5,16 +5,16 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- var path = require('path')
9
- var fs = require('./util/unwrapped-core').fs
10
- var logger = require('./logger').child({component: 'shimmer'})
11
- var INSTRUMENTATIONS = require('./instrumentations')()
12
- var properties = require('./util/properties')
13
- var shims = require('./shim')
8
+ const path = require('path')
9
+ const fs = require('./util/unwrapped-core').fs
10
+ const logger = require('./logger').child({ component: 'shimmer' })
11
+ const INSTRUMENTATIONS = require('./instrumentations')()
12
+ const properties = require('./util/properties')
13
+ const shims = require('./shim')
14
14
 
15
- var MODULE_TYPE = shims.constants.MODULE_TYPE
15
+ const MODULE_TYPE = shims.constants.MODULE_TYPE
16
16
 
17
- var CORE_INSTRUMENTATION = {
17
+ const CORE_INSTRUMENTATION = {
18
18
  child_process: {
19
19
  type: MODULE_TYPE.GENERIC,
20
20
  file: 'child_process.js'
@@ -73,114 +73,12 @@ const FORCE_MODULE_RESOLUTION_WARNING =
73
73
  * maneuver, but it should be pretty safe if there's a desire to reboot the
74
74
  * agent in flight.
75
75
  *
76
- * All of the wrapped methods are tracked in this variable and used by unwrapAll
76
+ * All of the wrapped methods are tracked in this constiable and used by unwrapAll
77
77
  * below.
78
78
  */
79
- var instrumented = []
79
+ let instrumented = []
80
80
 
81
- function applyDebugState(shimmer, shim, nodule) {
82
- if (shimmer.debug) {
83
- shim.enableDebug()
84
- instrumented.push(shim)
85
- instrumented.push({__NR_unwrap: function unwrapNodule() {
86
- delete nodule.__NR_instrumented_errored
87
- delete nodule.__NR_instrumented
88
- delete nodule.__NR_shim
89
- }})
90
- nodule.__NR_shim = shim
91
- }
92
- }
93
-
94
- /**
95
- * All instrumentation files must export the same interface: a single
96
- * initialization function that takes the agent and the module to be
97
- * instrumented.
98
- */
99
- function instrument(agent, nodule, moduleName, resolvedName) {
100
- var instrumentation = shimmer.registeredInstrumentations[moduleName]
101
- if (properties.hasOwn(nodule, '__NR_instrumented')
102
- || properties.hasOwn(nodule, '__NR_instrumented_errored')) {
103
- logger.trace(
104
- 'Already instrumented or failed to instrument %s, skipping redundant instrumentation',
105
- moduleName
106
- )
107
- return nodule
108
- }
109
-
110
-
111
- var shim = shims.createShimFromType(
112
- instrumentation.type,
113
- agent,
114
- moduleName,
115
- resolvedName
116
- )
117
-
118
- applyDebugState(shimmer, shim, nodule)
119
-
120
- try {
121
- if (instrumentation.onRequire(shim, nodule, moduleName) !== false) {
122
- nodule = shim.getExport(nodule)
123
- nodule.__NR_instrumented = true
124
- }
125
- } catch (instrumentationError) {
126
- nodule.__NR_instrumented_errored = true
127
- if (instrumentation.onError) {
128
- try {
129
- instrumentation.onError(instrumentationError)
130
- } catch (e) {
131
- logger.warn(
132
- e, instrumentationError,
133
- 'Custom instrumentation for %s failed, then the onError handler threw an error',
134
- moduleName
135
- )
136
- }
137
- } else {
138
- logger.warn(
139
- instrumentationError,
140
- 'Custom instrumentation for %s failed. Please report this to the ' +
141
- 'maintainers of the custom instrumentation.',
142
- moduleName
143
- )
144
- }
145
- }
146
-
147
- return nodule
148
- }
149
-
150
- function _firstPartyInstrumentation(agent, fileName, shim, nodule, moduleName) {
151
- var fullPath = path.resolve(fileName)
152
- if (!fs.existsSync(fileName)) {
153
- return logger.warn(
154
- 'Tried to load instrumentation from %s, but file does not exist',
155
- fullPath
156
- )
157
- }
158
- try {
159
- return require(fileName)(agent, nodule, moduleName, shim)
160
- } catch (error) {
161
- logger.warn(
162
- error,
163
- 'Failed to instrument module %s using %s',
164
- path.basename(fileName, '.js'),
165
- fullPath
166
- )
167
- }
168
- }
169
-
170
- function _postLoad(agent, nodule, name, resolvedName) {
171
- var instrumentation
172
- instrumentation = shimmer.getInstrumentationNameFromModuleName(name)
173
-
174
- // Check if this is a known instrumentation and then run it.
175
- if (shimmer.registeredInstrumentations[instrumentation]) {
176
- logger.trace('Instrumenting %s.', name)
177
- return instrument(agent, nodule, instrumentation, resolvedName)
178
- }
179
-
180
- return nodule
181
- }
182
-
183
- var shimmer = module.exports = {
81
+ const shimmer = (module.exports = {
184
82
  /**
185
83
  * If debug isn't false, the agent will retain references to wrapped methods
186
84
  * for the entire lifetime of the agent. Some instrumentation depends on
@@ -218,17 +116,18 @@ var shimmer = module.exports = {
218
116
  */
219
117
  wrapMethod: function wrapMethod(nodule, noduleName, methods, wrapper) {
220
118
  if (!methods) {
221
- return logger.warn(
222
- new Error(),
223
- "Must include a method name to wrap. Called from:"
224
- )
119
+ return logger.warn(new Error(), 'Must include a method name to wrap. Called from:')
225
120
  }
226
121
 
227
- if (!noduleName) noduleName = '[unknown]'
228
- if (!Array.isArray(methods)) methods = [methods]
122
+ if (!noduleName) {
123
+ noduleName = '[unknown]'
124
+ }
125
+ if (!Array.isArray(methods)) {
126
+ methods = [methods]
127
+ }
229
128
 
230
- methods.forEach(function cb_forEach(method) {
231
- var fqmn = noduleName + '.' + method
129
+ methods.forEach((method) => {
130
+ const fqmn = noduleName + '.' + method
232
131
 
233
132
  if (!nodule) {
234
133
  return logger.debug("Can't wrap %s from nonexistent object.", fqmn)
@@ -238,24 +137,31 @@ var shimmer = module.exports = {
238
137
  return logger.debug("Can't wrap %s without a wrapper generator.", fqmn)
239
138
  }
240
139
 
241
- var original = nodule[method]
140
+ const original = nodule[method]
242
141
 
243
- if (!original) return logger.trace("%s not defined, so not wrapping.", fqmn)
244
- if (original.__NR_unwrap) return logger.debug("%s already wrapped by agent.", fqmn)
142
+ if (!original) {
143
+ return logger.trace('%s not defined, so not wrapping.', fqmn)
144
+ }
145
+ if (original.__NR_unwrap) {
146
+ return logger.debug('%s already wrapped by agent.', fqmn)
147
+ }
245
148
 
246
- var wrapped = wrapper(original, method)
149
+ const wrapped = wrapper(original, method)
247
150
  Object.keys(original).forEach((key) => {
248
151
  wrapped[key] = original[key]
249
152
  })
250
153
  wrapped.__NR_original = original
154
+ // eslint-disable-next-line camelcase
251
155
  wrapped.__NR_unwrap = function __NR_unwrap() {
252
156
  nodule[method] = original
253
- logger.trace("Removed instrumentation from %s.", fqmn)
157
+ logger.trace('Removed instrumentation from %s.', fqmn)
254
158
  }
255
159
 
256
160
  nodule[method] = wrapped
257
- if (shimmer.debug) instrumented.push(wrapped)
258
- logger.trace("Instrumented %s.", fqmn)
161
+ if (shimmer.debug) {
162
+ instrumented.push(wrapped)
163
+ }
164
+ logger.trace('Instrumented %s.', fqmn)
259
165
  })
260
166
  },
261
167
 
@@ -277,34 +183,40 @@ var shimmer = module.exports = {
277
183
  */
278
184
  wrapDeprecated: function wrapDeprecated(nodule, noduleName, property, options) {
279
185
  if (!property) {
280
- logger.warn(new Error(), "Must include a function name to wrap. Called from:")
186
+ logger.warn(new Error(), 'Must include a function name to wrap. Called from:')
281
187
  return
282
188
  }
283
189
 
284
- if (!noduleName) noduleName = '[unknown]'
190
+ if (!noduleName) {
191
+ noduleName = '[unknown]'
192
+ }
285
193
 
286
- var fqmn = noduleName + '.' + property
194
+ const fqmn = noduleName + '.' + property
287
195
  if (!nodule) {
288
196
  logger.debug("Can't wrap %s from nonexistent object.", fqmn)
289
197
  return
290
198
  }
291
199
 
292
- var original = nodule[property]
200
+ const original = nodule[property]
293
201
  if (!original) {
294
- logger.trace("%s not defined, so not wrapping.", fqmn)
202
+ logger.trace('%s not defined, so not wrapping.', fqmn)
295
203
  return
296
204
  }
297
205
 
298
206
  delete nodule[property]
299
207
 
300
- var descriptor = {
208
+ const descriptor = {
301
209
  configurable: true,
302
210
  enumerable: true
303
211
  }
304
- if (options.get) descriptor.get = options.get
305
- if (options.set) descriptor.set = options.set
212
+ if (options.get) {
213
+ descriptor.get = options.get
214
+ }
215
+ if (options.set) {
216
+ descriptor.set = options.set
217
+ }
306
218
  Object.defineProperty(nodule, property, descriptor)
307
- logger.trace("Instrumented %s.", fqmn)
219
+ logger.trace('Instrumented %s.', fqmn)
308
220
 
309
221
  if (shimmer.debug) {
310
222
  instrumented.push({
@@ -319,30 +231,42 @@ var shimmer = module.exports = {
319
231
  },
320
232
 
321
233
  unwrapMethod: function unwrapMethod(nodule, noduleName, method) {
322
- if (!noduleName) noduleName = '[unknown]'
323
- if (!method) return logger.debug("Must include a method name to unwrap. " +
324
- "Called from: %s", new Error().stack)
234
+ if (!noduleName) {
235
+ noduleName = '[unknown]'
236
+ }
237
+ if (!method) {
238
+ return logger.debug(
239
+ 'Must include a method name to unwrap. ' + 'Called from: %s',
240
+ new Error().stack
241
+ )
242
+ }
325
243
 
326
- var fqmn = noduleName + '.' + method
244
+ const fqmn = noduleName + '.' + method
327
245
 
328
246
  if (!nodule) {
329
247
  return logger.debug("Can't unwrap %s from nonexistent object.", fqmn)
330
248
  }
331
249
 
332
- var wrapped = nodule[method]
250
+ const wrapped = nodule[method]
333
251
 
334
252
  // keep instrumented up to date
335
- var pos = instrumented.indexOf(wrapped)
336
- if (pos !== -1) instrumented.splice(pos, 1)
253
+ const pos = instrumented.indexOf(wrapped)
254
+ if (pos !== -1) {
255
+ instrumented.splice(pos, 1)
256
+ }
337
257
 
338
- if (!wrapped) return logger.debug("%s not defined, so not unwrapping.", fqmn)
339
- if (!wrapped.__NR_unwrap) return logger.debug("%s isn't unwrappable.", fqmn)
258
+ if (!wrapped) {
259
+ return logger.debug('%s not defined, so not unwrapping.', fqmn)
260
+ }
261
+ if (!wrapped.__NR_unwrap) {
262
+ return logger.debug("%s isn't unwrappable.", fqmn)
263
+ }
340
264
 
341
265
  wrapped.__NR_unwrap()
342
266
  },
343
267
 
344
268
  unwrapAll: function unwrapAll() {
345
- instrumented.forEach(function cb_forEach(wrapper) {
269
+ instrumented.forEach((wrapper) => {
346
270
  wrapper.__NR_unwrap()
347
271
  })
348
272
  instrumented = []
@@ -353,9 +277,9 @@ var shimmer = module.exports = {
353
277
  * have an opportunity to patch them with instrumentation.
354
278
  */
355
279
  patchModule: function patchModule(agent) {
356
- logger.trace("Wrapping module loader.")
357
- var Module = require('module')
358
- var filepathMap = {}
280
+ logger.trace('Wrapping module loader.')
281
+ const Module = require('module')
282
+ const filepathMap = {}
359
283
 
360
284
  shimmer.wrapMethod(Module, 'Module', '_resolveFilename', function wrapRes(resolve) {
361
285
  return function wrappedResolveFilename(file) {
@@ -404,8 +328,8 @@ var shimmer = module.exports = {
404
328
  },
405
329
 
406
330
  unpatchModule: function unpatchModule() {
407
- logger.trace("Unwrapping to previous module loader.")
408
- var Module = require('module')
331
+ logger.trace('Unwrapping to previous module loader.')
332
+ const Module = require('module')
409
333
 
410
334
  shimmer.unwrapMethod(Module, 'Module', '_resolveFilename')
411
335
  shimmer.unwrapMethod(Module, 'Module', '_load')
@@ -414,8 +338,8 @@ var shimmer = module.exports = {
414
338
  bootstrapInstrumentation: function bootstrapInstrumentation(agent) {
415
339
  // Instrument global.
416
340
  const globalShim = new shims.Shim(agent, 'globals', 'globals')
417
- applyDebugState(shimmer, globalShim, global)
418
- var globalsFilepath = path.join(__dirname, 'instrumentation', 'core', 'globals.js')
341
+ applyDebugState(globalShim, global)
342
+ const globalsFilepath = path.join(__dirname, 'instrumentation', 'core', 'globals.js')
419
343
  _firstPartyInstrumentation(agent, globalsFilepath, globalShim, global, 'globals')
420
344
 
421
345
  // Instrument each of the core modules.
@@ -427,27 +351,23 @@ var shimmer = module.exports = {
427
351
  try {
428
352
  uninstrumented = require(mojule)
429
353
  } catch (err) {
430
- logger.trace(
431
- 'Could not load core module %s got error %s',
432
- mojule,
433
- err
434
- )
354
+ logger.trace('Could not load core module %s got error %s', mojule, err)
435
355
  }
436
356
 
437
357
  const shim = shims.createShimFromType(core.type, agent, mojule, mojule)
438
- applyDebugState(shimmer, shim, core)
358
+ applyDebugState(shim, core)
439
359
  _firstPartyInstrumentation(agent, filePath, shim, uninstrumented, mojule)
440
360
  })
441
361
 
442
362
  // Register all the first-party instrumentations.
443
363
  Object.keys(INSTRUMENTATIONS).forEach(function forEachInstrumentation(moduleName) {
444
- var instrInfo = INSTRUMENTATIONS[moduleName]
364
+ const instrInfo = INSTRUMENTATIONS[moduleName]
445
365
  if (instrInfo.module) {
446
366
  // Because external instrumentations can change independent of
447
367
  // the agent core, we don't want breakages in them to entirely
448
368
  // disable the agent.
449
369
  try {
450
- var hooks = require(instrInfo.module + '/nr-hooks')
370
+ const hooks = require(instrInfo.module + '/nr-hooks')
451
371
  hooks.forEach(shimmer.registerInstrumentation)
452
372
  } catch (e) {
453
373
  logger.warn('Failed to load instrumentation for ' + instrInfo.module, e)
@@ -457,7 +377,7 @@ var shimmer = module.exports = {
457
377
  // TODO: Remove this code when amqplib instrumentation is made external.
458
378
  require('./instrumentation/amqplib').selfRegister(shimmer)
459
379
  } else {
460
- var fileName = path.join(__dirname, 'instrumentation', moduleName + '.js')
380
+ const fileName = path.join(__dirname, 'instrumentation', moduleName + '.js')
461
381
  shimmer.registerInstrumentation({
462
382
  moduleName: moduleName,
463
383
  type: instrInfo.type,
@@ -469,7 +389,7 @@ var shimmer = module.exports = {
469
389
  // Even though domain is a core module we add it as a registered
470
390
  // instrumentation to be lazy-loaded because we do not want to cause domain
471
391
  // usage.
472
- var domainPath = path.join(__dirname, 'instrumentation/core/domain.js')
392
+ const domainPath = path.join(__dirname, 'instrumentation/core/domain.js')
473
393
  shimmer.registerInstrumentation({
474
394
  moduleName: 'domain',
475
395
  type: null,
@@ -510,12 +430,13 @@ var shimmer = module.exports = {
510
430
  * the same.
511
431
  */
512
432
  getInstrumentationNameFromModuleName(moduleName) {
513
- var instrumentation
433
+ let instrumentation
514
434
  // XXX When updating these special cases, also update `uninstrumented`.
515
435
  // To allow for instrumenting both 'pg' and 'pg.js'.
516
436
  if (moduleName === 'pg.js') {
517
437
  instrumentation = 'pg'
518
- } if (moduleName === 'mysql2') {
438
+ }
439
+ if (moduleName === 'mysql2') {
519
440
  // mysql2 (https://github.com/sidorares/node-mysql2) is a drop in replacement for
520
441
  // mysql which conforms to the existing mysql API. If we see mysql2, treat it as
521
442
  // mysql
@@ -525,4 +446,101 @@ var shimmer = module.exports = {
525
446
  }
526
447
  return instrumentation
527
448
  }
449
+ })
450
+
451
+ function applyDebugState(shim, nodule) {
452
+ if (shimmer.debug) {
453
+ shim.enableDebug()
454
+ instrumented.push(shim)
455
+ instrumented.push({
456
+ __NR_unwrap: function unwrapNodule() {
457
+ delete nodule.__NR_instrumented_errored
458
+ delete nodule.__NR_instrumented
459
+ delete nodule.__NR_shim
460
+ }
461
+ })
462
+ nodule.__NR_shim = shim
463
+ }
464
+ }
465
+
466
+ /**
467
+ * All instrumentation files must export the same interface: a single
468
+ * initialization function that takes the agent and the module to be
469
+ * instrumented.
470
+ */
471
+ function instrument(agent, nodule, moduleName, resolvedName) {
472
+ const instrumentation = shimmer.registeredInstrumentations[moduleName]
473
+ if (
474
+ properties.hasOwn(nodule, '__NR_instrumented') ||
475
+ properties.hasOwn(nodule, '__NR_instrumented_errored')
476
+ ) {
477
+ logger.trace(
478
+ 'Already instrumented or failed to instrument %s, skipping redundant instrumentation',
479
+ moduleName
480
+ )
481
+ return nodule
482
+ }
483
+
484
+ const shim = shims.createShimFromType(instrumentation.type, agent, moduleName, resolvedName)
485
+
486
+ applyDebugState(shim, nodule)
487
+
488
+ try {
489
+ if (instrumentation.onRequire(shim, nodule, moduleName) !== false) {
490
+ nodule = shim.getExport(nodule)
491
+ nodule.__NR_instrumented = true
492
+ }
493
+ } catch (instrumentationError) {
494
+ nodule.__NR_instrumented_errored = true
495
+ if (instrumentation.onError) {
496
+ try {
497
+ instrumentation.onError(instrumentationError)
498
+ } catch (e) {
499
+ logger.warn(
500
+ e,
501
+ instrumentationError,
502
+ 'Custom instrumentation for %s failed, then the onError handler threw an error',
503
+ moduleName
504
+ )
505
+ }
506
+ } else {
507
+ logger.warn(
508
+ instrumentationError,
509
+ 'Custom instrumentation for %s failed. Please report this to the ' +
510
+ 'maintainers of the custom instrumentation.',
511
+ moduleName
512
+ )
513
+ }
514
+ }
515
+
516
+ return nodule
517
+ }
518
+
519
+ function _firstPartyInstrumentation(agent, fileName, shim, nodule, moduleName) {
520
+ const fullPath = path.resolve(fileName)
521
+ if (!fs.existsSync(fileName)) {
522
+ return logger.warn('Tried to load instrumentation from %s, but file does not exist', fullPath)
523
+ }
524
+ try {
525
+ return require(fileName)(agent, nodule, moduleName, shim)
526
+ } catch (error) {
527
+ logger.warn(
528
+ error,
529
+ 'Failed to instrument module %s using %s',
530
+ path.basename(fileName, '.js'),
531
+ fullPath
532
+ )
533
+ }
534
+ }
535
+
536
+ function _postLoad(agent, nodule, name, resolvedName) {
537
+ const instrumentation = shimmer.getInstrumentationNameFromModuleName(name)
538
+
539
+ // Check if this is a known instrumentation and then run it.
540
+ if (shimmer.registeredInstrumentations[instrumentation]) {
541
+ logger.trace('Instrumenting %s.', name)
542
+ return instrument(agent, nodule, instrumentation, resolvedName)
543
+ }
544
+
545
+ return nodule
528
546
  }