newrelic 9.5.0 → 9.7.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 (104) hide show
  1. package/NEWS.md +14 -0
  2. package/api.js +2 -0
  3. package/bin/test-naming-rules.js +1 -1
  4. package/esm-loader.mjs +1 -3
  5. package/index.js +6 -5
  6. package/lib/adaptive-sampler.js +1 -2
  7. package/lib/agent.js +2 -0
  8. package/lib/aggregators/event-aggregator.js +2 -2
  9. package/lib/attributes.js +2 -4
  10. package/lib/collector/api.js +20 -12
  11. package/lib/collector/facts.js +1 -3
  12. package/lib/collector/parse-response.js +3 -1
  13. package/lib/collector/remote-method.js +10 -10
  14. package/lib/config/attribute-filter.js +14 -16
  15. package/lib/config/default.js +544 -286
  16. package/lib/config/formatters.js +108 -0
  17. package/lib/config/harvest-config-validator.js +3 -5
  18. package/lib/config/index.js +74 -93
  19. package/lib/environment.js +6 -5
  20. package/lib/errors/error-collector.js +6 -3
  21. package/lib/errors/helper.js +10 -18
  22. package/lib/errors/index.js +12 -6
  23. package/lib/grpc/connection.js +12 -5
  24. package/lib/header-attributes.js +4 -2
  25. package/lib/header-processing.js +2 -2
  26. package/lib/instrumentation/@hapi/hapi.js +231 -1
  27. package/lib/instrumentation/{vision.js → @hapi/vision.js} +0 -0
  28. package/lib/instrumentation/@node-redis/client.js +2 -0
  29. package/lib/instrumentation/amqplib.js +2 -0
  30. package/lib/instrumentation/core/async_hooks.js +3 -4
  31. package/lib/instrumentation/core/globals.js +12 -10
  32. package/lib/instrumentation/core/http-outbound.js +17 -17
  33. package/lib/instrumentation/core/http.js +16 -27
  34. package/lib/instrumentation/core/timers.js +5 -1
  35. package/lib/instrumentation/fastify.js +1 -3
  36. package/lib/instrumentation/grpc-js/grpc.js +14 -3
  37. package/lib/instrumentation/memcached.js +5 -0
  38. package/lib/instrumentation/mongodb/common.js +3 -0
  39. package/lib/instrumentation/mongodb/v2-mongo.js +6 -3
  40. package/lib/instrumentation/mongodb.js +1 -1
  41. package/lib/instrumentation/mysql/mysql.js +6 -5
  42. package/lib/instrumentation/nr-winston-transport.js +3 -4
  43. package/lib/instrumentation/promise.js +22 -18
  44. package/lib/instrumentation/redis.js +2 -0
  45. package/lib/instrumentation/undici.js +12 -15
  46. package/lib/instrumentations.js +1 -1
  47. package/lib/metrics/mapper.js +2 -3
  48. package/lib/metrics/metric-aggregator.js +1 -3
  49. package/lib/metrics/names.js +19 -15
  50. package/lib/metrics/normalizer/rule.js +6 -7
  51. package/lib/metrics/normalizer/tx_segment.js +3 -2
  52. package/lib/metrics/normalizer.js +5 -3
  53. package/lib/parse-proc-cpuinfo.js +11 -6
  54. package/lib/serverless/api-gateway.js +3 -4
  55. package/lib/serverless/aws-lambda.js +3 -3
  56. package/lib/shim/conglomerate-shim.js +2 -3
  57. package/lib/shim/constants.js +1 -16
  58. package/lib/shim/datastore-shim.js +24 -105
  59. package/lib/shim/index.js +7 -0
  60. package/lib/shim/message-shim.js +2 -0
  61. package/lib/shim/promise-shim.js +66 -59
  62. package/lib/shim/shim.js +44 -89
  63. package/lib/shim/transaction-shim.js +1 -1
  64. package/lib/shim/webframework-shim.js +4 -8
  65. package/lib/shimmer.js +29 -23
  66. package/lib/spans/map-to-streaming-type.js +0 -2
  67. package/lib/spans/span-context.js +2 -0
  68. package/lib/spans/span-event-aggregator.js +2 -2
  69. package/lib/spans/span-event.js +2 -2
  70. package/lib/spans/span-streamer.js +4 -0
  71. package/lib/spans/streaming-span-event-aggregator.js +2 -4
  72. package/lib/spans/streaming-span-event.js +3 -2
  73. package/lib/symbols.js +26 -0
  74. package/lib/system-info.js +4 -7
  75. package/lib/timer.js +8 -6
  76. package/lib/transaction/dt-payload.js +4 -3
  77. package/lib/transaction/handle.js +12 -2
  78. package/lib/transaction/index.js +19 -18
  79. package/lib/transaction/name-state.js +17 -2
  80. package/lib/transaction/trace/aggregator.js +4 -12
  81. package/lib/transaction/trace/index.js +7 -5
  82. package/lib/transaction/trace/segment.js +6 -11
  83. package/lib/transaction/tracecontext.js +10 -6
  84. package/lib/transaction/tracer/index.js +35 -43
  85. package/lib/transaction/transaction-event-aggregator.js +1 -3
  86. package/lib/util/arity.js +4 -9
  87. package/lib/util/attribute-types.js +1 -2
  88. package/lib/util/byte-limit.js +1 -3
  89. package/lib/util/cat.js +16 -13
  90. package/lib/util/codec.js +0 -2
  91. package/lib/util/copy.js +1 -2
  92. package/lib/util/deep-equal.js +7 -0
  93. package/lib/util/flatten.js +4 -6
  94. package/lib/util/hashes.js +1 -3
  95. package/lib/util/process-version.js +2 -3
  96. package/lib/util/properties.js +2 -51
  97. package/lib/util/stream-sink.js +2 -0
  98. package/lib/util/urltils.js +4 -10
  99. package/newrelic.js +1 -1
  100. package/package.json +2 -1
  101. package/lib/config/env.js +0 -294
  102. package/lib/instrumentation/hapi/hapi.js +0 -207
  103. package/lib/instrumentation/hapi/shared.js +0 -28
  104. package/lib/instrumentation/hapi.js +0 -254
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 69] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
8
10
  const genericRecorder = require('../metrics/recorders/generic')
9
11
  const logger = require('../logger.js').child({ component: 'WebFrameworkShim' })
10
12
  const metrics = require('../metrics/names')
@@ -13,6 +15,7 @@ const Shim = require('./shim')
13
15
  const specs = require('./specs')
14
16
  const urltils = require('../util/urltils')
15
17
  const util = require('util')
18
+ const symbols = require('../symbols')
16
19
 
17
20
  /**
18
21
  * An enumeration of well-known web frameworks so that new instrumentations can
@@ -54,13 +57,6 @@ const MIDDLEWARE_TYPE_NAMES = {
54
57
  ROUTER: 'ROUTER'
55
58
  }
56
59
 
57
- /**
58
- * Name of the key used to store transaction information on `req` and `res`.
59
- *
60
- * @private
61
- */
62
- const TRANSACTION_INFO_KEY = '__NR_transactionInfo'
63
-
64
60
  /**
65
61
  * Constructs a shim associated with the given agent instance, specialized for
66
62
  * instrumenting web frameworks.
@@ -1036,7 +1032,7 @@ function _makeNextBinder(nextDetails, txInfo) {
1036
1032
  */
1037
1033
  function _getTransactionInfo(shim, req) {
1038
1034
  try {
1039
- return req[TRANSACTION_INFO_KEY] || null
1035
+ return req[symbols.transactionInfo] || null
1040
1036
  } catch (e) {
1041
1037
  shim.logger.debug(e, 'Failed to fetch transaction info from req')
1042
1038
  return null
package/lib/shimmer.js CHANGED
@@ -14,6 +14,7 @@ const properties = require('./util/properties')
14
14
  const shims = require('./shim')
15
15
 
16
16
  const NAMES = require('./metrics/names')
17
+ const symbols = require('./symbols')
17
18
 
18
19
  const MODULE_TYPE = shims.constants.MODULE_TYPE
19
20
 
@@ -97,7 +98,7 @@ const shimmer = (module.exports = {
97
98
  * @returns {bool} True if `fn` exists and has an attached original, else false.
98
99
  */
99
100
  isWrapped: function isWrapped(fn) {
100
- return !!(fn && fn.__NR_original)
101
+ return !!(fn && fn[symbols.original])
101
102
  },
102
103
 
103
104
  /**
@@ -118,7 +119,8 @@ const shimmer = (module.exports = {
118
119
  */
119
120
  wrapMethod: function wrapMethod(nodule, noduleName, methods, wrapper) {
120
121
  if (!methods) {
121
- return logger.warn(new Error(), 'Must include a method name to wrap. Called from:')
122
+ logger.warn(new Error(), 'Must include a method name to wrap. Called from:')
123
+ return
122
124
  }
123
125
 
124
126
  if (!noduleName) {
@@ -132,29 +134,33 @@ const shimmer = (module.exports = {
132
134
  const fqmn = noduleName + '.' + method
133
135
 
134
136
  if (!nodule) {
135
- return logger.debug("Can't wrap %s from nonexistent object.", fqmn)
137
+ logger.debug("Can't wrap %s from nonexistent object.", fqmn)
138
+ return
136
139
  }
137
140
 
138
141
  if (!wrapper) {
139
- return logger.debug("Can't wrap %s without a wrapper generator.", fqmn)
142
+ logger.debug("Can't wrap %s without a wrapper generator.", fqmn)
143
+ return
140
144
  }
141
145
 
142
146
  const original = nodule[method]
143
147
 
144
148
  if (!original) {
145
- return logger.trace('%s not defined, so not wrapping.', fqmn)
149
+ logger.trace('%s not defined, so not wrapping.', fqmn)
150
+ return
146
151
  }
147
- if (original.__NR_unwrap) {
148
- return logger.debug('%s already wrapped by agent.', fqmn)
152
+ if (original[symbols.unwrap]) {
153
+ logger.debug('%s already wrapped by agent.', fqmn)
154
+ return
149
155
  }
150
156
 
151
157
  const wrapped = wrapper(original, method)
152
158
  Object.keys(original).forEach((key) => {
153
159
  wrapped[key] = original[key]
154
160
  })
155
- wrapped.__NR_original = original
161
+ wrapped[symbols.original] = original
156
162
  // eslint-disable-next-line camelcase
157
- wrapped.__NR_unwrap = function __NR_unwrap() {
163
+ wrapped[symbols.unwrap] = function unwrap() {
158
164
  nodule[method] = original
159
165
  logger.trace('Removed instrumentation from %s.', fqmn)
160
166
  }
@@ -221,7 +227,7 @@ const shimmer = (module.exports = {
221
227
 
222
228
  if (shimmer.debug) {
223
229
  instrumented.push({
224
- __NR_unwrap: function unwrapDeprecated() {
230
+ [symbols.unwrap]: function unwrapDeprecated() {
225
231
  delete nodule[property]
226
232
  nodule[property] = original
227
233
  }
@@ -259,16 +265,16 @@ const shimmer = (module.exports = {
259
265
  if (!wrapped) {
260
266
  return logger.debug('%s not defined, so not unwrapping.', fqmn)
261
267
  }
262
- if (!wrapped.__NR_unwrap) {
268
+ if (!wrapped[symbols.unwrap]) {
263
269
  return logger.debug("%s isn't unwrappable.", fqmn)
264
270
  }
265
271
 
266
- wrapped.__NR_unwrap()
272
+ wrapped[symbols.unwrap]()
267
273
  },
268
274
 
269
275
  unwrapAll: function unwrapAll() {
270
276
  instrumented.forEach((wrapper) => {
271
- wrapper.__NR_unwrap()
277
+ wrapper[symbols.unwrap]()
272
278
  })
273
279
  instrumented = []
274
280
  },
@@ -472,7 +478,7 @@ const shimmer = (module.exports = {
472
478
  // This is to not break the public API
473
479
  // previously it would just call instrumentation
474
480
  // and not check the result
475
- return returnModule ? result : !!result.__NR_instrumented
481
+ return returnModule ? result : !!result[symbols.instrumented]
476
482
  }
477
483
  })
478
484
 
@@ -481,13 +487,13 @@ function applyDebugState(shim, nodule) {
481
487
  shim.enableDebug()
482
488
  instrumented.push(shim)
483
489
  instrumented.push({
484
- __NR_unwrap: function unwrapNodule() {
485
- delete nodule.__NR_instrumented_errored
486
- delete nodule.__NR_instrumented
487
- delete nodule.__NR_shim
490
+ [symbols.unwrap]: function unwrapNodule() {
491
+ delete nodule[symbols.instrumentedErrored]
492
+ delete nodule[symbols.instrumented]
493
+ delete nodule[symbols.shim]
488
494
  }
489
495
  })
490
- nodule.__NR_shim = shim
496
+ nodule[symbols.shim] = shim
491
497
  }
492
498
  }
493
499
 
@@ -504,8 +510,8 @@ function applyDebugState(shim, nodule) {
504
510
  function instrumentPostLoad(agent, nodule, moduleName, resolvedName) {
505
511
  const instrumentation = shimmer.registeredInstrumentations[moduleName]
506
512
  if (
507
- properties.hasOwn(nodule, '__NR_instrumented') ||
508
- properties.hasOwn(nodule, '__NR_instrumented_errored')
513
+ properties.hasOwn(nodule, symbols.instrumented) ||
514
+ properties.hasOwn(nodule, symbols.instrumentedErrored)
509
515
  ) {
510
516
  logger.trace(
511
517
  'Already instrumented or failed to instrument %s, skipping redundant instrumentation',
@@ -527,10 +533,10 @@ function instrumentPostLoad(agent, nodule, moduleName, resolvedName) {
527
533
  try {
528
534
  if (instrumentation.onRequire(shim, nodule, moduleName) !== false) {
529
535
  nodule = shim.getExport(nodule)
530
- nodule.__NR_instrumented = true
536
+ nodule[symbols.instrumented] = true
531
537
  }
532
538
  } catch (instrumentationError) {
533
- nodule.__NR_instrumented_errored = true
539
+ nodule[symbols.instrumentedErrored] = true
534
540
  if (instrumentation.onError) {
535
541
  try {
536
542
  instrumentation.onError(instrumentationError)
@@ -42,8 +42,6 @@ function mapToStreamingType(value) {
42
42
  [protoTypeString]: value
43
43
  }
44
44
  }
45
-
46
- return
47
45
  }
48
46
 
49
47
  module.exports = mapToStreamingType
@@ -40,6 +40,8 @@ class SpanContext {
40
40
  * ends with an ignored error status code.
41
41
  *
42
42
  * Last error wins.
43
+ *
44
+ * @param details
43
45
  */
44
46
  setError(details) {
45
47
  this.hasError = true
@@ -63,8 +63,8 @@ class SpanEventAggregator extends EventAggregator {
63
63
  *
64
64
  * @param {TraceSegment} segment - The segment to add.
65
65
  * @param {string} [parentId=null] - The GUID of the parent span.
66
- *
67
- * @return {boolean} True if the segment was added, or false if it was discarded.
66
+ * @param isRoot
67
+ * @returns {boolean} True if the segment was added, or false if it was discarded.
68
68
  */
69
69
  addSegment(segment, parentId, isRoot) {
70
70
  // Check if the priority would be accepted before creating the event object.
@@ -83,8 +83,8 @@ class SpanEvent {
83
83
  *
84
84
  * @param {TraceSegment} segment - The segment to turn into a span event.
85
85
  * @param {?string} [parentId=null] - The ID of the segment's parent.
86
- *
87
- * @return {SpanEvent} The constructed event.
86
+ * @param isRoot
87
+ * @returns {SpanEvent} The constructed event.
88
88
  */
89
89
  static fromSegment(segment, parentId = null, isRoot = false) {
90
90
  const spanContext = segment.getSpanContext()
@@ -83,6 +83,8 @@ class SpanStreamer {
83
83
  * Sends the span over the stream. Spans are only sent here if the stream is
84
84
  * in a writable state. If the stream becomes unwritable after sending the
85
85
  * span, a drain event handler is setup to continue writing when possible.
86
+ *
87
+ * @param span
86
88
  */
87
89
  send(span) {
88
90
  // false indicates the stream has reached the highWaterMark
@@ -104,6 +106,8 @@ class SpanStreamer {
104
106
  * initially blocked, used to time how long the stream was blocked. If this
105
107
  * is not defined, it is assumed this is being called after a reconnect,
106
108
  * and the metric is not used.
109
+ *
110
+ * @param waitDrainStart
107
111
  */
108
112
  drain(waitDrainStart) {
109
113
  // Metric can be used to see how frequently completing drains as well as
@@ -60,8 +60,6 @@ class StreamingSpanEventAggregator extends Aggregator {
60
60
  }
61
61
 
62
62
  this.emit(`finished ${this.method} data send.`)
63
-
64
- return
65
63
  }
66
64
 
67
65
  /**
@@ -78,8 +76,8 @@ class StreamingSpanEventAggregator extends Aggregator {
78
76
  *
79
77
  * @param {TraceSegment} segment - The segment to add.
80
78
  * @param {string} [parentId=null] - The GUID of the parent span.
81
- *
82
- * @return {bool} True if the segment was added, or false if it was discarded.
79
+ * @param isRoot
80
+ * @returns {bool} True if the segment was added, or false if it was discarded.
83
81
  */
84
82
  addSegment(segment, parentId, isRoot) {
85
83
  if (!this.started) {
@@ -61,6 +61,7 @@ class StreamingSpanEvent {
61
61
 
62
62
  /**
63
63
  * Add a key/value pair to the Span's custom/user attributes collection.
64
+ *
64
65
  * @param {string} key Name of the attribute to be stored.
65
66
  * @param {string|boolean|number} value Value of the attribute to be stored.
66
67
  * @param {boolean} [truncateExempt=false] Set to true if attribute should not be truncated.
@@ -75,6 +76,7 @@ class StreamingSpanEvent {
75
76
 
76
77
  /**
77
78
  * Add a key/value pair to the Span's agent attributes collection.
79
+ *
78
80
  * @param {string} key Name of the attribute to be stored.
79
81
  * @param {string|boolean|number} value Value of the attribute to be stored.
80
82
  * @param {boolean} [truncateExempt=false] Set to true if attribute should not be truncated.
@@ -95,13 +97,12 @@ class StreamingSpanEvent {
95
97
 
96
98
  toStreamingFormat() {
97
99
  // Attributes are pre-formatted.
98
- const formatted = {
100
+ return {
99
101
  trace_id: this._traceId,
100
102
  intrinsics: this._intrinsicAttributes,
101
103
  user_attributes: this._customAttributes,
102
104
  agent_attributes: this._agentAttributes
103
105
  }
104
- return formatted
105
106
  }
106
107
 
107
108
  static fromSegment(segment, parentId = null, isRoot = false) {
package/lib/symbols.js ADDED
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Copyright 2022 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ module.exports = {
9
+ cache: Symbol('cache'),
10
+ context: Symbol('context'),
11
+ databaseName: Symbol('databaseName'),
12
+ disableDT: Symbol('Disable distributed tracing'), // description for backwards compatibility
13
+ executorContext: Symbol('executorContext'),
14
+ instrumented: Symbol('instrumented'),
15
+ instrumentedErrored: Symbol('instrumentedErrored'),
16
+ name: Symbol('name'),
17
+ onceExecuted: Symbol('onceExecuted'),
18
+ offTheRecord: Symbol('offTheRecord'),
19
+ original: Symbol('original'),
20
+ segment: Symbol('segment'),
21
+ shim: Symbol('shim'),
22
+ storeDatabase: Symbol('storeDatabase'),
23
+ transaction: Symbol('transaction'),
24
+ transactionInfo: Symbol('transactionInfo'),
25
+ unwrap: Symbol('unwrap')
26
+ }
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 29] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
8
10
  const exec = require('child_process').exec
9
11
  const readProc = require('./utilization/common').readProc
10
12
  const getBootId = require('./utilization/docker-info').getBootId
@@ -21,7 +23,7 @@ function isInteger(i) {
21
23
  return i === parseInt(i, 10)
22
24
  }
23
25
 
24
- function fetchSystemInfo(agent, callback) {
26
+ function fetchSystemInfo(agent, callback, numTasks = 5) {
25
27
  const config = agent.config
26
28
  const systemInfo = {
27
29
  processorArch: os.arch()
@@ -74,7 +76,6 @@ function fetchSystemInfo(agent, callback) {
74
76
  }
75
77
 
76
78
  let tasksDone = 0
77
- const numTasks = 5
78
79
  function finishedResponse() {
79
80
  if (++tasksDone === numTasks) {
80
81
  callback(null, systemInfo)
@@ -174,11 +175,7 @@ module.exports._getMemoryStats = function getMemoryStats(callback) {
174
175
  }
175
176
 
176
177
  function getKernelVersion(callback) {
177
- if (platform.match(/darwin/i)) {
178
- getSysctlValue(['kern.version'], function getMem(version) {
179
- callback(version)
180
- })
181
- } else if (platform.match(/bsd/i)) {
178
+ if (platform.match(/darwin/i) || platform.match(/bsd/i)) {
182
179
  getSysctlValue(['kern.version'], function getMem(version) {
183
180
  callback(version)
184
181
  })
package/lib/timer.js CHANGED
@@ -6,7 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  /**
9
-
9
+
10
10
  * Explicit enumeration of the states a transaction can be in:
11
11
  *
12
12
  * PENDING upon instantiation (implicitly, no start time set)
@@ -106,21 +106,21 @@ Timer.prototype.softEnd = function softEnd() {
106
106
  }
107
107
 
108
108
  /**
109
- * @return {bool} Is this timer currently running?
109
+ * @returns {bool} Is this timer currently running?
110
110
  */
111
111
  Timer.prototype.isRunning = function isRunning() {
112
112
  return this.state === RUNNING
113
113
  }
114
114
 
115
115
  /**
116
- * @return {bool} Is this timer still alive?
116
+ * @returns {bool} Is this timer still alive?
117
117
  */
118
118
  Timer.prototype.isActive = function isActive() {
119
119
  return this.state < STOPPED
120
120
  }
121
121
 
122
122
  /**
123
- * @return {bool} Has the timer been touched or ended?
123
+ * @returns {bool} Has the timer been touched or ended?
124
124
  */
125
125
  Timer.prototype.hasEnd = function hasEnd() {
126
126
  return !!this.hrDuration
@@ -192,7 +192,7 @@ Timer.prototype.getDurationInMillis = function getDurationInMillis() {
192
192
  /**
193
193
  * Get a single object containing the interval this timer was active.
194
194
  *
195
- * @return {Array} 2-tuple of start time in milliseconds, end time in
195
+ * @returns {Array} 2-tuple of start time in milliseconds, end time in
196
196
  * milliseconds.
197
197
  */
198
198
  Timer.prototype.toRange = function toRange() {
@@ -205,7 +205,7 @@ Timer.prototype.toRange = function toRange() {
205
205
  * milliseconds since start.
206
206
  *
207
207
  * @param {Timer} other The point relative to which this timer started.
208
- * @return {number} The offset in (floating-point) milliseconds.
208
+ * @returns {number} The offset in (floating-point) milliseconds.
209
209
  */
210
210
  Timer.prototype.startedRelativeTo = function startedRelativeTo(other) {
211
211
  if (this.hrstart && other.hrstart) {
@@ -220,6 +220,8 @@ Timer.prototype.startedRelativeTo = function startedRelativeTo(other) {
220
220
 
221
221
  /**
222
222
  * Returns true if this timer ends after the other.
223
+ *
224
+ * @param other
223
225
  */
224
226
  Timer.prototype.endsAfter = function compare(other) {
225
227
  return this.getDurationInMillis() + this.start > other.getDurationInMillis() + other.start
@@ -15,7 +15,8 @@ module.exports = class DistributedTracePayload {
15
15
  * The class responsible for producing distributed trace payloads.
16
16
  * Created by calling {@link TransactionHandle#_createDistributedTracePayload}.
17
17
  *
18
- * @constructor
18
+ * @param payload
19
+ * @class
19
20
  */
20
21
  constructor(payload) {
21
22
  logger.trace('DistributedTracePayload created with %s', payload)
@@ -27,7 +28,7 @@ module.exports = class DistributedTracePayload {
27
28
  }
28
29
 
29
30
  /**
30
- * @returns {String} The base64 encoded JSON representation of the
31
+ * @returns {string} The base64 encoded JSON representation of the
31
32
  * distributed trace payload.
32
33
  */
33
34
  text() {
@@ -38,7 +39,7 @@ module.exports = class DistributedTracePayload {
38
39
  /**
39
40
  * Construct a payload suitable for HTTP transport.
40
41
  *
41
- * @returns {String} The base64 encoded JSON representation of the
42
+ * @returns {string} The base64 encoded JSON representation of the
42
43
  * distributed trace payload.
43
44
  */
44
45
  httpSafe() {
@@ -14,7 +14,9 @@ class TransactionHandle {
14
14
  * A light representation of a transaction instance, returned by calling
15
15
  * {@link API#getTransaction}.
16
16
  *
17
- * @constructor
17
+ * @param transaction
18
+ * @param metrics
19
+ * @class
18
20
  */
19
21
  constructor(transaction, metrics) {
20
22
  this._transaction = transaction
@@ -54,7 +56,9 @@ class TransactionHandle {
54
56
  * Parsing incoming headers for use in a distributed trace.
55
57
  * W3C TraceContext format is preferred over the NewRelic DT format.
56
58
  * NewRelic DT format will be used if no `traceparent` header is found.
59
+ *
57
60
  * @param @param {string} [transportType='Unknown'] - The transport type that delivered the trace.
61
+ * @param transportType
58
62
  * @param {object} headers - Headers to search for supported formats. Keys must be lowercase.
59
63
  */
60
64
  acceptDistributedTraceHeaders(transportType, headers) {
@@ -64,7 +68,8 @@ class TransactionHandle {
64
68
 
65
69
  /**
66
70
  * Inserts distributed trace headers into the provided headers map.
67
- * @param {Object} headers
71
+ *
72
+ * @param {object} headers
68
73
  */
69
74
  insertDistributedTraceHeaders(headers) {
70
75
  incrementApiSupportMetric(this._metrics, 'insertDistributedTraceHeaders')
@@ -74,6 +79,11 @@ class TransactionHandle {
74
79
 
75
80
  module.exports = TransactionHandle
76
81
 
82
+ /**
83
+ *
84
+ * @param metrics
85
+ * @param functionName
86
+ */
77
87
  function incrementApiSupportMetric(metrics, functionName) {
78
88
  if (!metrics) {
79
89
  logger.warnOnce(
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 29] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
8
10
  const errorHelper = require('../errors/helper')
9
11
  const hashes = require('../util/hashes')
10
12
  const logger = require('../logger').child({ component: 'transaction' })
@@ -18,6 +20,9 @@ const url = require('url')
18
20
  const urltils = require('../util/urltils')
19
21
  const TraceContext = require('./tracecontext').TraceContext
20
22
  const Logs = require('./logs')
23
+ const DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC = 'DistributedTrace/AcceptPayload/Exception'
24
+ const DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC = 'DistributedTrace/AcceptPayload/ParseException'
25
+ const REQUEST_PARAMS_PATH = 'request.parameters.'
21
26
 
22
27
  /*
23
28
  *
@@ -425,7 +430,7 @@ function finalizeNameFromUri(requestURL, statusCode) {
425
430
  this.nameState.forEachParams(function forEachRouteParams(params) {
426
431
  for (const key in params) {
427
432
  if (props.hasOwn(params, key)) {
428
- this.trace.attributes.addAttribute(DESTS.NONE, 'request.parameters.' + key, params[key])
433
+ this.trace.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
429
434
 
430
435
  const segment = this.agent.tracer.getSegment()
431
436
 
@@ -435,7 +440,7 @@ function finalizeNameFromUri(requestURL, statusCode) {
435
440
  key
436
441
  )
437
442
  } else {
438
- segment.attributes.addAttribute(DESTS.NONE, 'request.parameters.' + key, params[key])
443
+ segment.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
439
444
  }
440
445
  }
441
446
  }
@@ -484,7 +489,7 @@ Transaction.prototype._markAsWeb = function _markAsWeb(rawURL) {
484
489
  const params = urltils.parseParameters(rawURL)
485
490
  for (const key in params) {
486
491
  if (props.hasOwn(params, key)) {
487
- this.trace.attributes.addAttribute(DESTS.NONE, 'request.parameters.' + key, params[key])
492
+ this.trace.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
488
493
 
489
494
  const segment = this.agent.tracer.getSegment()
490
495
 
@@ -494,7 +499,7 @@ Transaction.prototype._markAsWeb = function _markAsWeb(rawURL) {
494
499
  key
495
500
  )
496
501
  } else {
497
- segment.attributes.addAttribute(DESTS.NONE, 'request.parameters.' + key, params[key])
502
+ segment.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
498
503
  }
499
504
  }
500
505
  }
@@ -1058,7 +1063,7 @@ function _acceptDistributedTracePayload(payload, transport) {
1058
1063
  trustedAccount
1059
1064
  )
1060
1065
 
1061
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/Exception')
1066
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC)
1062
1067
  return
1063
1068
  }
1064
1069
 
@@ -1075,14 +1080,14 @@ function _acceptDistributedTracePayload(payload, transport) {
1075
1080
  if (!parsed.d) {
1076
1081
  logger.warn('Received a distributed trace payload with no data field', this.id)
1077
1082
  }
1078
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/ParseException')
1083
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
1079
1084
  return
1080
1085
  }
1081
1086
 
1082
1087
  const majorVersion = parsed.v && typeof parsed.v[0] === 'number' && parsed.v[0]
1083
1088
  if (majorVersion == null) {
1084
1089
  logger.warn('Invalid distributed trace payload, not accepting')
1085
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/Exception')
1090
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC)
1086
1091
  }
1087
1092
  if (majorVersion > 0) {
1088
1093
  // TODO: Add DistributedTracePayload class?
@@ -1094,7 +1099,7 @@ function _acceptDistributedTracePayload(payload, transport) {
1094
1099
 
1095
1100
  if (!data) {
1096
1101
  logger.warn('No distributed trace data received, not accepting payload')
1097
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/Exception')
1102
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC)
1098
1103
  return
1099
1104
  }
1100
1105
 
@@ -1103,7 +1108,7 @@ function _acceptDistributedTracePayload(payload, transport) {
1103
1108
  })
1104
1109
  // Either parentSpanId or parentId are required.
1105
1110
  if (!requiredKeysExist || (data.tx == null && data.id == null)) {
1106
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/ParseException')
1111
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
1107
1112
  return
1108
1113
  }
1109
1114
 
@@ -1157,7 +1162,7 @@ Transaction.prototype._getParsedPayload = function _getParsedPayload(payload) {
1157
1162
  payload = Buffer.from(payload, 'base64').toString('utf-8')
1158
1163
  } catch (err) {
1159
1164
  logger.warn(err, 'Got unparseable distributed trace payload in transaction %s', this.id)
1160
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/ParseException')
1165
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
1161
1166
  return null
1162
1167
  }
1163
1168
  }
@@ -1165,7 +1170,7 @@ Transaction.prototype._getParsedPayload = function _getParsedPayload(payload) {
1165
1170
  parsed = JSON.parse(payload)
1166
1171
  } catch (err) {
1167
1172
  logger.warn(err, 'Failed to parse distributed trace payload in transaction %s', this.id)
1168
- this.agent.recordSupportability('DistributedTrace/AcceptPayload/ParseException')
1173
+ this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
1169
1174
  return null
1170
1175
  }
1171
1176
  }
@@ -1300,24 +1305,20 @@ Transaction.prototype.addRequestParameters = addRequestParameters
1300
1305
  * 'request.parameters.{key}'. These attributes will only be created
1301
1306
  * when 'request.parameters.*' is included in the attribute config.
1302
1307
  *
1303
- * @param {object.<string, string>} requestParameters
1308
+ * @param {Object<string, string>} requestParameters
1304
1309
  */
1305
1310
  function addRequestParameters(requestParameters) {
1306
1311
  for (const key in requestParameters) {
1307
1312
  if (props.hasOwn(requestParameters, key)) {
1308
1313
  this.trace.attributes.addAttribute(
1309
1314
  DESTS.NONE,
1310
- 'request.parameters.' + key,
1315
+ REQUEST_PARAMS_PATH + key,
1311
1316
  requestParameters[key]
1312
1317
  )
1313
1318
 
1314
1319
  const segment = this.baseSegment
1315
1320
 
1316
- segment.attributes.addAttribute(
1317
- DESTS.NONE,
1318
- 'request.parameters.' + key,
1319
- requestParameters[key]
1320
- )
1321
+ segment.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, requestParameters[key])
1321
1322
  }
1322
1323
  }
1323
1324
  }