newrelic 9.4.0 → 9.6.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.
@@ -13,21 +13,20 @@ const cat = require('../../util/cat')
13
13
  const instrumentOutbound = require('./http-outbound')
14
14
  const url = require('url')
15
15
  const urltils = require('../../util/urltils')
16
- const properties = require('../../util/properties')
17
16
  const headerAttributes = require('../../header-attributes')
18
17
  const headerProcessing = require('../../header-processing')
19
18
 
20
19
  const NAMES = require('../../metrics/names')
21
20
  const DESTS = require('../../config/attribute-filter').DESTINATIONS
22
21
 
22
+ const symbols = require('../../symbols')
23
+
23
24
  /*
24
25
  *
25
26
  * CONSTANTS
26
27
  *
27
28
  */
28
- const NR_CONNECTION_PROP = '__NR__connection'
29
29
  const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
30
- const TRANSACTION_INFO_KEY = '__NR_transactionInfo'
31
30
 
32
31
  // For incoming requests this instrumentation functions by wrapping
33
32
  // `http.createServer` and `http.Server#addListener`. The former merely sets the
@@ -55,12 +54,6 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
55
54
  // Store the transaction information on the request and response.
56
55
  const txInfo = storeTxInfo(transaction, request, response)
57
56
 
58
- // Hook for web framework instrumentations that don't have easy access to
59
- // the request entry point.
60
- if (properties.hasOwn(this, '__NR_onRequestStarted')) {
61
- this.__NR_onRequestStarted(request, response)
62
- }
63
-
64
57
  if (request) {
65
58
  initializeRequest(transaction, request)
66
59
  }
@@ -204,7 +197,6 @@ function storeTxInfo(transaction, request, response) {
204
197
  logger.debug('Missing request or response object! Not storing transaction info.')
205
198
  return
206
199
  }
207
- const hideInternal = transaction.agent.config.transaction_tracer.hide_internals
208
200
 
209
201
  const txInfo = {
210
202
  transaction: transaction,
@@ -212,12 +204,7 @@ function storeTxInfo(transaction, request, response) {
212
204
  errorHandled: false,
213
205
  error: null
214
206
  }
215
- if (hideInternal) {
216
- properties.setInternal(request, TRANSACTION_INFO_KEY, txInfo)
217
- properties.setInternal(response, TRANSACTION_INFO_KEY, txInfo)
218
- } else {
219
- request[TRANSACTION_INFO_KEY] = response[TRANSACTION_INFO_KEY] = txInfo
220
- }
207
+ request[symbols.transactionInfo] = response[symbols.transactionInfo] = txInfo
221
208
 
222
209
  logger.trace('Stored transaction %s information on request and response', transaction.id)
223
210
 
@@ -245,7 +232,7 @@ function wrapResponseEnd(agent, proto) {
245
232
  }
246
233
 
247
234
  return function wrappedResEnd() {
248
- const txInfo = this && this[TRANSACTION_INFO_KEY]
235
+ const txInfo = this && this[symbols.transactionInfo]
249
236
  if (!txInfo) {
250
237
  return end.apply(this, arguments)
251
238
  }
@@ -393,9 +380,9 @@ function wrapRequest(agent, request) {
393
380
  const reqArgs = [options, cb]
394
381
 
395
382
  // Don't pollute metrics and calls with NR connections
396
- const internalOnly = options && options[NR_CONNECTION_PROP]
383
+ const internalOnly = options && options[symbols.offTheRecord]
397
384
  if (internalOnly) {
398
- delete options[NR_CONNECTION_PROP]
385
+ delete options[symbols.offTheRecord]
399
386
  }
400
387
 
401
388
  // If this is not a request we're recording, exit early.
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const symbols = require('../../symbols')
9
+
8
10
  module.exports = initialize
9
11
 
10
12
  function initialize(agent, timers, moduleName, shim) {
@@ -53,7 +55,7 @@ function initialize(agent, timers, moduleName, shim) {
53
55
  function wrapClearTimeout(shim, fn) {
54
56
  return function wrappedClearTimeout(timer) {
55
57
  if (timer && timer._onTimeout) {
56
- const segment = timer._onTimeout.__NR_segment
58
+ const segment = timer._onTimeout[symbols.segment]
57
59
  if (segment && !segment.opaque) {
58
60
  segment.ignore = true
59
61
  }
@@ -7,6 +7,7 @@
7
7
 
8
8
  const dbutils = require('../../db/utils')
9
9
  const properties = require('../../util/properties')
10
+ const symbols = require('../../symbols')
10
11
 
11
12
  exports.callbackInitialize = function callbackInitialize(shim, mysql) {
12
13
  shim.setDatastore(shim.MYSQL)
@@ -17,7 +18,7 @@ exports.callbackInitialize = function callbackInitialize(shim, mysql) {
17
18
  shim.logger.debug('Wrapping Connection#query')
18
19
  if (wrapQueryable(shim, connection, false)) {
19
20
  const connProto = Object.getPrototypeOf(connection)
20
- shim.setInternalProperty(connProto, '__NR_storeDatabase', true)
21
+ connProto[symbols.storeDatabase] = true
21
22
  shim.unwrap(mysql, 'createConnection')
22
23
  }
23
24
  }
@@ -133,7 +134,7 @@ function wrapQueryable(shim, queryable, isPoolQuery) {
133
134
  describe = describePoolQuery
134
135
  } else {
135
136
  describe = describeQuery
136
- shim.setInternalProperty(proto, '__NR_databaseName', null)
137
+ proto[symbols.databaseName] = null
137
138
  }
138
139
 
139
140
  shim.recordQuery(proto, 'query', describe)
@@ -214,7 +215,7 @@ function getInstanceParameters(shim, queryable, query) {
214
215
  const parameters = { host: null, port_path_or_id: null, database_name: null }
215
216
  let conf = queryable.config
216
217
  conf = (conf && conf.connectionConfig) || conf
217
- let databaseName = queryable.__NR_databaseName || null
218
+ let databaseName = queryable[symbols.databaseName] || null
218
219
  if (conf) {
219
220
  parameters.database_name = databaseName = databaseName || conf.database
220
221
 
@@ -235,10 +236,10 @@ function getInstanceParameters(shim, queryable, query) {
235
236
  }
236
237
 
237
238
  function storeDatabaseName(shim, queryable, query) {
238
- if (queryable.__NR_storeDatabase) {
239
+ if (queryable[symbols.storeDatabase]) {
239
240
  const databaseName = dbutils.extractDatabaseChangeFromUse(query)
240
241
  if (databaseName) {
241
- shim.setInternalProperty(queryable, '__NR_databaseName', databaseName)
242
+ queryable[symbols.databaseName] = databaseName
242
243
  }
243
244
  }
244
245
  }
@@ -8,6 +8,7 @@
8
8
  const util = require('util')
9
9
  const properties = require('../util/properties')
10
10
  const shimmer = require('../shimmer')
11
+ const symbols = require('../symbols')
11
12
 
12
13
  /**
13
14
  * @namespace Library.Spec
@@ -213,13 +214,13 @@ module.exports = function initialize(agent, library, spec) {
213
214
  self: null,
214
215
  args: null
215
216
  }
216
- if (!this.__NR_context) {
217
+ if (!this[symbols.context]) {
217
218
  const segmentName = 'Promise ' + executor.name || '<anonymous>'
218
219
  const segment = _createSegment(segmentName)
219
220
  Contextualizer.link(null, this, segment, spec.useFinally)
220
221
  }
221
222
  const args = [].slice.call(arguments)
222
- args[0] = wrapExecutorContext(context, this.__NR_context.getSegment())
223
+ args[0] = wrapExecutorContext(context, this[symbols.context].getSegment())
223
224
  const ret = caller.apply(this, args)
224
225
 
225
226
  // Bluebird catches executor errors and auto-rejects when it catches them,
@@ -256,8 +257,8 @@ module.exports = function initialize(agent, library, spec) {
256
257
  function wrapResolver(context, fn) {
257
258
  return function wrappedResolveReject(val) {
258
259
  const promise = context.promise
259
- if (promise && promise.__NR_context) {
260
- promise.__NR_context.getSegment().touch()
260
+ if (promise && promise[symbols.context]) {
261
+ promise[symbols.context].getSegment().touch()
261
262
  }
262
263
  fn(val)
263
264
  }
@@ -333,15 +334,15 @@ module.exports = function initialize(agent, library, spec) {
333
334
  }
334
335
 
335
336
  return function __NR_wrappedThenHandler() {
336
- if (!next || !next.__NR_context) {
337
+ if (!next || !next[symbols.context]) {
337
338
  return fn.apply(this, arguments)
338
339
  }
339
340
 
340
- let promSegment = next.__NR_context.getSegment()
341
+ let promSegment = next[symbols.context].getSegment()
341
342
  const segmentName = segmentNamePrefix + (fn.name || '<anonymous>')
342
343
  const segment = _createSegment(segmentName, promSegment)
343
344
  if (segment && segment !== promSegment) {
344
- next.__NR_context.setSegment(segment)
345
+ next[symbols.context].setSegment(segment)
345
346
  promSegment = segment
346
347
  }
347
348
 
@@ -350,7 +351,7 @@ module.exports = function initialize(agent, library, spec) {
350
351
  ret = agent.tracer.bindFunction(fn, promSegment, true).apply(this, arguments)
351
352
  } finally {
352
353
  if (ret && typeof ret.then === 'function') {
353
- ret = next.__NR_context.continue(ret)
354
+ ret = next[symbols.context].continue(ret)
354
355
  }
355
356
  }
356
357
  return ret
@@ -453,9 +454,9 @@ function Contextualizer(idx, context, useFinally) {
453
454
  module.exports.Contextualizer = Contextualizer
454
455
 
455
456
  Contextualizer.link = function link(prev, next, segment, useFinally) {
456
- let ctxlzr = prev && prev.__NR_context
457
+ let ctxlzr = prev && prev[symbols.context]
457
458
  if (ctxlzr && !ctxlzr.isActive()) {
458
- ctxlzr = prev.__NR_context = null
459
+ ctxlzr = prev[symbols.context] = null
459
460
  }
460
461
 
461
462
  if (ctxlzr) {
@@ -497,17 +498,17 @@ Contextualizer.link = function link(prev, next, segment, useFinally) {
497
498
  const idx = ctxlzr.child === false ? ctxlzr.context.branch() : ctxlzr.idx
498
499
 
499
500
  // Create a new context for this next promise.
500
- next.__NR_context = new Contextualizer(idx, ctxlzr.context, ctxlzr.useFinally)
501
- next.__NR_context.parentIdx = ctxlzr.idx
501
+ next[symbols.context] = new Contextualizer(idx, ctxlzr.context, ctxlzr.useFinally)
502
+ next[symbols.context].parentIdx = ctxlzr.idx
502
503
 
503
504
  // If this was our first child, remember it in case we have a 2nd.
504
505
  if (ctxlzr.child === null) {
505
- ctxlzr.child = next.__NR_context
506
+ ctxlzr.child = next[symbols.context]
506
507
  }
507
508
  } else if (segment) {
508
509
  // This next promise is the root of a chain. Either there was no previous
509
510
  // promise or the promise was created out of context.
510
- next.__NR_context = new Contextualizer(0, new Context(segment), useFinally)
511
+ next[symbols.context] = new Contextualizer(0, new Context(segment), useFinally)
511
512
  }
512
513
  }
513
514
 
@@ -538,7 +539,7 @@ Contextualizer.prototype.toJSON = function toJSON() {
538
539
 
539
540
  Contextualizer.prototype.continue = function continueContext(prom) {
540
541
  const self = this
541
- const nextContext = prom.__NR_context
542
+ const nextContext = prom[symbols.context]
542
543
  if (!nextContext) {
543
544
  return prom
544
545
  }
@@ -10,10 +10,7 @@ const recordExternal = require('../metrics/recorders/http_external')
10
10
  const logger = require('../logger').child({ component: 'undici' })
11
11
  const NAMES = require('../metrics/names')
12
12
  const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
13
- const SYMBOLS = {
14
- SEGMENT: Symbol('__NR_segment'),
15
- PARENT_SEGMENT: Symbol('__NR_parent_segment')
16
- }
13
+ const symbols = require('../symbols')
17
14
  const { executionAsyncResource } = require('async_hooks')
18
15
 
19
16
  let diagnosticsChannel = null
@@ -52,11 +49,11 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
52
49
  if (agent.config.feature_flag.undici_async_tracking) {
53
50
  const resource = executionAsyncResource()
54
51
 
55
- if (!resource[SYMBOLS.PARENT_SEGMENT]) {
52
+ if (!resource[symbols.parentSegment]) {
56
53
  const parent = shim.getSegment()
57
- resource[SYMBOLS.PARENT_SEGMENT] = parent
54
+ resource[symbols.parentSegment] = parent
58
55
  }
59
- return resource[SYMBOLS.PARENT_SEGMENT]
56
+ return resource[symbols.parentSegment]
60
57
  }
61
58
  return shim.getSegment()
62
59
  }
@@ -71,7 +68,7 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
71
68
  */
72
69
  diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
73
70
  const parent = getParentSegment()
74
- request[SYMBOLS.PARENT_SEGMENT] = parent
71
+ request[symbols.parentSegment] = parent
75
72
  if (!parent || (parent && parent.opaque)) {
76
73
  logger.trace(
77
74
  'Not capturing data for outbound request (%s) because parent segment opaque (%s)',
@@ -114,7 +111,7 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
114
111
  * @param {TLSSocket | net.Socket} socket active socket connection
115
112
  */
116
113
  diagnosticsChannel.channel('undici:client:sendHeaders').subscribe(({ request, socket }) => {
117
- const parentSegment = request[SYMBOLS.PARENT_SEGMENT]
114
+ const parentSegment = request[symbols.parentSegment]
118
115
  if (!parentSegment || (parentSegment && parentSegment.opaque)) {
119
116
  return
120
117
  }
@@ -143,7 +140,7 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
143
140
  segment.addSpanAttribute(`request.parameters.${key}`, value)
144
141
  })
145
142
  segment.addAttribute('procedure', request.method || 'GET')
146
- request[SYMBOLS.SEGMENT] = segment
143
+ request[symbols.segment] = segment
147
144
  }
148
145
  })
149
146
 
@@ -157,7 +154,7 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
157
154
  * @param {object} params.response { statusCode, headers, statusText }
158
155
  */
159
156
  diagnosticsChannel.channel('undici:request:headers').subscribe(({ request, response }) => {
160
- const activeSegment = request[SYMBOLS.SEGMENT]
157
+ const activeSegment = request[symbols.segment]
161
158
  if (!activeSegment) {
162
159
  return
163
160
  }
@@ -211,8 +208,8 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
211
208
  * @param {Error} error
212
209
  */
213
210
  function endAndRestoreSegment(ctx, error) {
214
- const activeSegment = ctx[SYMBOLS.SEGMENT]
215
- const parentSegment = ctx[SYMBOLS.PARENT_SEGMENT]
211
+ const activeSegment = ctx[symbols.segment]
212
+ const parentSegment = ctx[symbols.parentSegment]
216
213
  if (activeSegment) {
217
214
  activeSegment.end()
218
215
 
@@ -238,5 +235,3 @@ module.exports = function addUndiciChannels(agent, undici, modName, shim) {
238
235
  shim.agent.errors.add(tx, error)
239
236
  }
240
237
  }
241
-
242
- module.exports.SYMBOLS = SYMBOLS
@@ -36,7 +36,7 @@ module.exports = function instrumentations() {
36
36
  'restify': { type: MODULE_TYPE.WEB_FRAMEWORK },
37
37
  'superagent': { module: '@newrelic/superagent' },
38
38
  'undici': { type: MODULE_TYPE.TRANSACTION },
39
- 'vision': { type: MODULE_TYPE.WEB_FRAMEWORK },
39
+ '@hapi/vision': { type: MODULE_TYPE.WEB_FRAMEWORK },
40
40
  'when': { type: null },
41
41
  'winston': { type: MODULE_TYPE.GENERIC }
42
42
  }
@@ -12,7 +12,7 @@
12
12
  * @readonly
13
13
  * @enum {string}
14
14
  */
15
- const MODULE_TYPE = {
15
+ exports.MODULE_TYPE = {
16
16
  /** Utility/generic module, such as pooling libraries. */
17
17
  GENERIC: 'generic',
18
18
 
@@ -34,18 +34,3 @@ const MODULE_TYPE = {
34
34
  /** Web server framework module, such as Express or Restify. */
35
35
  WEB_FRAMEWORK: 'web-framework'
36
36
  }
37
-
38
- /**
39
- * Enumeration of symbols used by shims.
40
- *
41
- * @memberof Shim.prototype
42
- * @readonly
43
- * @enum {Symbol}
44
- */
45
- const SYMBOLS = {
46
- /** Indicates distributed tracing should be disabled for a single request. */
47
- DISABLE_DT: Symbol('Disable distributed tracing')
48
- }
49
-
50
- exports.MODULE_TYPE = MODULE_TYPE
51
- exports.SYMBOLS = SYMBOLS
@@ -14,6 +14,7 @@ const ParsedStatement = require('../db/parsed-statement')
14
14
  const Shim = require('./shim')
15
15
  const urltils = require('../util/urltils')
16
16
  const util = require('util')
17
+ const symbols = require('../symbols')
17
18
 
18
19
  /**
19
20
  * An enumeration of well-known datastores so that new instrumentations can use
@@ -616,7 +617,7 @@ function bindRowCallbackSegment(args, cbIdx, parentSegment) {
616
617
  }, parentSegment)
617
618
 
618
619
  // Mark this as wrapped and put it in the args array.
619
- this.setInternalProperty(wrapper, '__NR_original', cb)
620
+ wrapper[symbols.original] = cb
620
621
  args[idx] = wrapper
621
622
  }
622
623
 
@@ -7,6 +7,7 @@
7
7
 
8
8
  const logger = require('../logger').child({ component: 'PromiseShim' })
9
9
  const Shim = require('./shim')
10
+ const symbols = require('../symbols')
10
11
 
11
12
  /**
12
13
  * A helper class for wrapping promise modules.
@@ -108,7 +109,7 @@ class PromiseShim extends Shim {
108
109
  post: function postPromise(shim, Promise, name, args) {
109
110
  // This extra property is added by `_wrapExecutorContext` in the pre step.
110
111
  const executor = args[0]
111
- const context = executor && executor.__NR_executorContext
112
+ const context = executor && executor[symbols.executorContext]
112
113
  if (!context || !shim.isFunction(context.executor)) {
113
114
  return
114
115
  }
@@ -159,14 +160,14 @@ class PromiseShim extends Shim {
159
160
  return caller.apply(this, arguments)
160
161
  }
161
162
 
162
- if (!this.__NR_context) {
163
+ if (!this[symbols.context]) {
163
164
  Contextualizer.link(null, this, parent)
164
165
  }
165
166
 
166
167
  const args = shim.argsToArray.apply(shim, arguments)
167
168
  _wrapExecutorContext(shim, args)
168
169
  const ret = caller.apply(this, args)
169
- const context = args[0].__NR_executorContext
170
+ const context = args[0][symbols.executorContext]
170
171
  context.promise = this
171
172
 
172
173
  // Bluebird catches executor errors and auto-rejects when it catches them,
@@ -343,7 +344,7 @@ function _wrapExecutorContext(shim, args) {
343
344
  self: null,
344
345
  args: null
345
346
  }
346
- contextExporter.__NR_executorContext = context
347
+ contextExporter[symbols.executorContext] = context
347
348
  args[0] = contextExporter
348
349
 
349
350
  function contextExporter(resolve, reject) {
@@ -360,8 +361,8 @@ function _wrapExecutorContext(shim, args) {
360
361
  function _wrapResolver(context, fn) {
361
362
  return function wrappedResolveReject(val) {
362
363
  const promise = context.promise
363
- if (promise && promise.__NR_context) {
364
- promise.__NR_context.getSegment().touch()
364
+ if (promise && promise[symbols.context]) {
365
+ promise[symbols.context].getSegment().touch()
365
366
  }
366
367
  fn(val)
367
368
  }
@@ -409,14 +410,14 @@ function _wrapThen(shim, fn, name, useAllParams) {
409
410
  }
410
411
 
411
412
  return function __NR_wrappedThenHandler() {
412
- if (!next || !next.__NR_context) {
413
+ if (!next || !next[symbols.context]) {
413
414
  return handler.apply(this, arguments)
414
415
  }
415
416
 
416
- let promSegment = next.__NR_context.getSegment()
417
+ let promSegment = next[symbols.context].getSegment()
417
418
  const segment = promSegment || shim.getSegment()
418
419
  if (segment && segment !== promSegment) {
419
- next.__NR_context.setSegment(segment)
420
+ next[symbols.context].setSegment(segment)
420
421
  promSegment = segment
421
422
  }
422
423
 
@@ -425,7 +426,7 @@ function _wrapThen(shim, fn, name, useAllParams) {
425
426
  ret = shim.applySegment(handler, promSegment, true, this, arguments)
426
427
  } finally {
427
428
  if (ret && typeof ret.then === 'function') {
428
- ret = next.__NR_context.continueContext(ret)
429
+ ret = next[symbols.context].continueContext(ret)
429
430
  }
430
431
  }
431
432
  return ret
@@ -459,9 +460,9 @@ class Contextualizer {
459
460
  }
460
461
 
461
462
  static link(prev, next, segment) {
462
- let ctxlzr = prev && prev.__NR_context
463
+ let ctxlzr = prev && prev[symbols.context]
463
464
  if (ctxlzr && !ctxlzr.isActive()) {
464
- ctxlzr = prev.__NR_context = null
465
+ ctxlzr = prev[symbols.context] = null
465
466
  }
466
467
 
467
468
  if (ctxlzr) {
@@ -503,17 +504,17 @@ class Contextualizer {
503
504
  const idx = ctxlzr.child === false ? ctxlzr.context.branch() : ctxlzr.idx
504
505
 
505
506
  // Create a new context for this next promise.
506
- next.__NR_context = new Contextualizer(idx, ctxlzr.context)
507
- next.__NR_context.parentIdx = ctxlzr.idx
507
+ next[symbols.context] = new Contextualizer(idx, ctxlzr.context)
508
+ next[symbols.context].parentIdx = ctxlzr.idx
508
509
 
509
510
  // If this was our first child, remember it in case we have a 2nd.
510
511
  if (ctxlzr.child === null) {
511
- ctxlzr.child = next.__NR_context
512
+ ctxlzr.child = next[symbols.context]
512
513
  }
513
514
  } else if (segment) {
514
515
  // This next promise is the root of a chain. Either there was no previous
515
516
  // promise or the promise was created out of context.
516
- next.__NR_context = new Contextualizer(0, new Context(segment))
517
+ next[symbols.context] = new Contextualizer(0, new Context(segment))
517
518
  }
518
519
  }
519
520
 
@@ -542,7 +543,7 @@ class Contextualizer {
542
543
 
543
544
  continueContext(prom) {
544
545
  const self = this
545
- const nextContext = prom.__NR_context
546
+ const nextContext = prom[symbols.context]
546
547
  if (!nextContext) {
547
548
  return prom
548
549
  }