newrelic 8.0.0 → 8.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.
Files changed (173) hide show
  1. package/NEWS.md +5023 -4922
  2. package/THIRD_PARTY_NOTICES.md +618 -209
  3. package/api.js +156 -219
  4. package/bin/test-naming-rules.js +57 -51
  5. package/bin/tracetractor +0 -1
  6. package/index.js +7 -14
  7. package/lib/agent.js +111 -114
  8. package/lib/aggregators/base-aggregator.js +1 -1
  9. package/lib/aggregators/event-aggregator.js +6 -6
  10. package/lib/attributes.js +13 -14
  11. package/lib/collector/api.js +44 -54
  12. package/lib/collector/facts.js +68 -66
  13. package/lib/collector/http-agents.js +36 -32
  14. package/lib/collector/key-parser.js +1 -1
  15. package/lib/collector/parse-response.js +1 -2
  16. package/lib/collector/remote-method.js +69 -61
  17. package/lib/collector/serverless.js +13 -18
  18. package/lib/collector/ssl/certificates.js +1056 -1056
  19. package/lib/config/attribute-filter.js +109 -101
  20. package/lib/config/default.js +35 -21
  21. package/lib/config/env.js +17 -12
  22. package/lib/config/harvest-config-validator.js +1 -1
  23. package/lib/config/hsm.js +1 -1
  24. package/lib/config/index.js +240 -234
  25. package/lib/config/lasp.js +3 -3
  26. package/lib/config/merge-server-config.js +8 -6
  27. package/lib/custom-events/custom-event-aggregator.js +1 -1
  28. package/lib/db/parse-sql.js +13 -16
  29. package/lib/db/parsed-statement.js +13 -19
  30. package/lib/db/query-parsers/sql.js +12 -15
  31. package/lib/db/query-sample.js +16 -12
  32. package/lib/db/query-trace-aggregator.js +16 -16
  33. package/lib/db/statement-matcher.js +5 -5
  34. package/lib/db/utils.js +2 -2
  35. package/lib/environment.js +210 -175
  36. package/lib/errors/error-collector.js +20 -33
  37. package/lib/errors/error-event-aggregator.js +1 -1
  38. package/lib/errors/error-trace-aggregator.js +3 -4
  39. package/lib/errors/helper.js +23 -32
  40. package/lib/errors/index.js +31 -43
  41. package/lib/feature_flags.js +3 -4
  42. package/lib/grpc/connection/states.js +6 -6
  43. package/lib/grpc/connection.js +35 -46
  44. package/lib/header-attributes.js +55 -59
  45. package/lib/header-processing.js +1 -1
  46. package/lib/instrumentation/amqplib.js +34 -43
  47. package/lib/instrumentation/bluebird.js +63 -22
  48. package/lib/instrumentation/cassandra-driver.js +8 -4
  49. package/lib/instrumentation/connect.js +7 -6
  50. package/lib/instrumentation/core/async_hooks.js +16 -9
  51. package/lib/instrumentation/core/child_process.js +20 -28
  52. package/lib/instrumentation/core/crypto.js +1 -7
  53. package/lib/instrumentation/core/dns.js +3 -7
  54. package/lib/instrumentation/core/domain.js +4 -10
  55. package/lib/instrumentation/core/fs.js +22 -37
  56. package/lib/instrumentation/core/globals.js +4 -8
  57. package/lib/instrumentation/core/http-outbound.js +20 -114
  58. package/lib/instrumentation/core/http.js +61 -128
  59. package/lib/instrumentation/core/inspector.js +7 -11
  60. package/lib/instrumentation/core/net.js +3 -1
  61. package/lib/instrumentation/core/timers.js +21 -28
  62. package/lib/instrumentation/core/zlib.js +3 -11
  63. package/lib/instrumentation/director.js +4 -4
  64. package/lib/instrumentation/express.js +12 -10
  65. package/lib/instrumentation/fastify/spec-builders.js +5 -0
  66. package/lib/instrumentation/fastify.js +37 -10
  67. package/lib/instrumentation/generic-pool.js +1 -1
  68. package/lib/instrumentation/hapi/hapi-17.js +20 -21
  69. package/lib/instrumentation/hapi/shared.js +1 -1
  70. package/lib/instrumentation/hapi.js +37 -37
  71. package/lib/instrumentation/ioredis.js +8 -9
  72. package/lib/instrumentation/memcached.js +41 -45
  73. package/lib/instrumentation/mongodb/common.js +221 -0
  74. package/lib/instrumentation/mongodb/constants.js +87 -0
  75. package/lib/instrumentation/mongodb/v2-mongo.js +110 -0
  76. package/lib/instrumentation/mongodb/v3-mongo.js +80 -0
  77. package/lib/instrumentation/mongodb/v4-mongo.js +90 -0
  78. package/lib/instrumentation/mongodb.js +20 -312
  79. package/lib/instrumentation/mysql.js +51 -44
  80. package/lib/instrumentation/oracle.js +24 -28
  81. package/lib/instrumentation/pg.js +34 -25
  82. package/lib/instrumentation/promise.js +65 -62
  83. package/lib/instrumentation/q.js +2 -2
  84. package/lib/instrumentation/redis.js +38 -38
  85. package/lib/instrumentation/restify.js +1 -1
  86. package/lib/instrumentation/vision.js +4 -4
  87. package/lib/instrumentation/when.js +12 -4
  88. package/lib/instrumentations.js +25 -25
  89. package/lib/logger.js +6 -6
  90. package/lib/metrics/index.js +50 -30
  91. package/lib/metrics/mapper.js +15 -15
  92. package/lib/metrics/metric-aggregator.js +5 -10
  93. package/lib/metrics/names.js +8 -7
  94. package/lib/metrics/normalizer/rule.js +14 -15
  95. package/lib/metrics/normalizer/tx_segment.js +33 -29
  96. package/lib/metrics/normalizer.js +51 -54
  97. package/lib/metrics/recorders/custom.js +8 -6
  98. package/lib/metrics/recorders/distributed-trace.js +3 -18
  99. package/lib/metrics/recorders/generic.js +6 -5
  100. package/lib/metrics/recorders/http.js +11 -13
  101. package/lib/metrics/recorders/http_external.js +8 -10
  102. package/lib/metrics/recorders/message-transaction.js +7 -18
  103. package/lib/metrics/recorders/other.js +7 -17
  104. package/lib/parse-proc-cpuinfo.js +26 -31
  105. package/lib/parse-proc-meminfo.js +5 -3
  106. package/lib/prioritized-attributes.js +14 -19
  107. package/lib/priority-queue.js +11 -11
  108. package/lib/proxy/grpc.js +1 -1
  109. package/lib/reservoir.js +12 -6
  110. package/lib/sampler.js +33 -34
  111. package/lib/serverless/api-gateway.js +3 -3
  112. package/lib/serverless/aws-lambda.js +28 -37
  113. package/lib/shim/conglomerate-shim.js +4 -4
  114. package/lib/shim/datastore-shim.js +61 -67
  115. package/lib/shim/index.js +10 -11
  116. package/lib/shim/message-shim.js +149 -151
  117. package/lib/shim/promise-shim.js +19 -14
  118. package/lib/shim/shim.js +131 -125
  119. package/lib/shim/specs/index.js +21 -22
  120. package/lib/shim/transaction-shim.js +52 -210
  121. package/lib/shim/webframework-shim.js +75 -85
  122. package/lib/shimmer.js +184 -166
  123. package/lib/spans/create-span-event-aggregator.js +11 -8
  124. package/lib/spans/span-context.js +4 -10
  125. package/lib/spans/span-event-aggregator.js +68 -13
  126. package/lib/spans/span-event.js +6 -8
  127. package/lib/spans/span-streamer.js +10 -18
  128. package/lib/spans/streaming-span-attributes.js +1 -1
  129. package/lib/spans/streaming-span-event-aggregator.js +1 -1
  130. package/lib/spans/streaming-span-event.js +4 -4
  131. package/lib/stats/apdex.js +7 -13
  132. package/lib/stats/index.js +14 -19
  133. package/lib/system-info.js +29 -25
  134. package/lib/timer.js +35 -21
  135. package/lib/transaction/dt-payload.js +1 -1
  136. package/lib/transaction/handle.js +19 -19
  137. package/lib/transaction/index.js +133 -151
  138. package/lib/transaction/name-state.js +18 -19
  139. package/lib/transaction/trace/aggregator.js +78 -73
  140. package/lib/transaction/trace/exclusive-time-calculator.js +9 -13
  141. package/lib/transaction/trace/index.js +37 -35
  142. package/lib/transaction/trace/segment.js +56 -73
  143. package/lib/transaction/tracecontext.js +38 -46
  144. package/lib/transaction/tracer/index.js +130 -91
  145. package/lib/transaction/transaction-event-aggregator.js +29 -31
  146. package/lib/uninstrumented.js +11 -12
  147. package/lib/util/arity.js +2 -2
  148. package/lib/util/attribute-types.js +1 -5
  149. package/lib/util/byte-limit.js +4 -5
  150. package/lib/util/cat.js +270 -33
  151. package/lib/util/codec.js +10 -6
  152. package/lib/util/copy.js +2 -2
  153. package/lib/util/deep-equal.js +51 -21
  154. package/lib/util/flatten.js +9 -6
  155. package/lib/util/hashes.js +16 -16
  156. package/lib/util/label-parser.js +22 -28
  157. package/lib/util/logger.js +53 -35
  158. package/lib/util/process-version.js +3 -3
  159. package/lib/util/properties.js +5 -5
  160. package/lib/util/sql/obfuscate.js +21 -31
  161. package/lib/util/stream-sink.js +5 -6
  162. package/lib/util/unwrapped-core.js +2 -2
  163. package/lib/util/urltils.js +26 -30
  164. package/lib/utilization/aws-info.js +8 -9
  165. package/lib/utilization/azure-info.js +37 -35
  166. package/lib/utilization/common.js +17 -16
  167. package/lib/utilization/docker-info.js +14 -16
  168. package/lib/utilization/gcp-info.js +38 -37
  169. package/lib/utilization/index.js +5 -5
  170. package/lib/utilization/kubernetes-info.js +2 -2
  171. package/lib/utilization/pcf-info.js +12 -12
  172. package/package.json +23 -6
  173. package/stub_api.js +16 -14
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
  }
@@ -10,21 +10,24 @@ const SpanEventAggregator = require('./span-event-aggregator')
10
10
  const StreamingSpanEventAggregator = require('./streaming-span-event-aggregator')
11
11
 
12
12
  function createSpanEventAggregator(config, collector, metrics) {
13
- const trace_observer = config.infinite_tracing.trace_observer
13
+ const traceObserver = config.infinite_tracing.trace_observer
14
14
 
15
- if (trace_observer.host) {
16
- trace_observer.host = trace_observer.host.trim()
15
+ if (traceObserver.host) {
16
+ traceObserver.host = traceObserver.host.trim()
17
17
 
18
- if (typeof trace_observer.port !== 'string') {
19
- trace_observer.port = String(trace_observer.port)
18
+ if (typeof traceObserver.port !== 'string') {
19
+ traceObserver.port = String(traceObserver.port)
20
20
  }
21
- trace_observer.port = trace_observer.port.trim()
21
+ traceObserver.port = traceObserver.port.trim()
22
22
 
23
23
  try {
24
24
  return createStreamingAggregator(config, collector, metrics)
25
25
  } catch (err) {
26
- logger.warn(err, 'Failed to create streaming span event aggregator for infinite tracing. ' +
27
- 'Reverting to standard span event aggregator and disabling infinite tracing')
26
+ logger.warn(
27
+ err,
28
+ 'Failed to create streaming span event aggregator for infinite tracing. ' +
29
+ 'Reverting to standard span event aggregator and disabling infinite tracing'
30
+ )
28
31
  config.infinite_tracing.trace_observer = {
29
32
  host: '',
30
33
  port: ''
@@ -5,9 +5,9 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const {MAXIMUM_CUSTOM_ATTRIBUTES} = require('../attributes')
9
- const {PrioritizedAttributes, ATTRIBUTE_PRIORITY} = require('../prioritized-attributes')
10
- const {DESTINATIONS} = require('../config/attribute-filter')
8
+ const { MAXIMUM_CUSTOM_ATTRIBUTES } = require('../attributes')
9
+ const { PrioritizedAttributes, ATTRIBUTE_PRIORITY } = require('../prioritized-attributes')
10
+ const { DESTINATIONS } = require('../config/attribute-filter')
11
11
 
12
12
  // Scoping impacts memoization. We could decide to add a scope instead of including
13
13
  // spans in segment scope in the future.
@@ -31,13 +31,7 @@ class SpanContext {
31
31
  }
32
32
 
33
33
  addCustomAttribute(key, value, priority) {
34
- this.customAttributes.addAttribute(
35
- DESTINATIONS.SPAN_EVENT,
36
- key,
37
- value,
38
- false,
39
- priority
40
- )
34
+ this.customAttributes.addAttribute(DESTINATIONS.SPAN_EVENT, key, value, false, priority)
41
35
  }
42
36
 
43
37
  /**