newrelic 9.6.0 → 9.7.1

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 (100) hide show
  1. package/NEWS.md +40 -16
  2. package/THIRD_PARTY_NOTICES.md +203 -2
  3. package/api.js +155 -101
  4. package/bin/test-naming-rules.js +1 -1
  5. package/esm-loader.mjs +1 -3
  6. package/lib/adaptive-sampler.js +1 -2
  7. package/lib/agent.js +29 -80
  8. package/lib/aggregators/event-aggregator.js +2 -2
  9. package/lib/attributes.js +2 -4
  10. package/lib/collector/api.js +252 -211
  11. package/lib/collector/facts.js +1 -3
  12. package/lib/collector/parse-response.js +3 -1
  13. package/lib/collector/remote-method.js +8 -9
  14. package/lib/config/attribute-filter.js +42 -34
  15. package/lib/config/default.js +60 -17
  16. package/lib/config/harvest-config-validator.js +3 -5
  17. package/lib/config/index.js +263 -199
  18. package/lib/environment.js +22 -17
  19. package/lib/errors/error-collector.js +123 -51
  20. package/lib/errors/helper.js +10 -18
  21. package/lib/errors/index.js +63 -47
  22. package/lib/grpc/connection.js +12 -5
  23. package/lib/header-attributes.js +4 -2
  24. package/lib/header-processing.js +2 -2
  25. package/lib/instrumentation/@hapi/hapi.js +56 -48
  26. package/lib/instrumentation/@node-redis/client.js +50 -39
  27. package/lib/instrumentation/amqplib.js +116 -149
  28. package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -9
  29. package/lib/instrumentation/core/globals.js +12 -9
  30. package/lib/instrumentation/core/http-outbound.js +200 -83
  31. package/lib/instrumentation/core/http.js +10 -8
  32. package/lib/instrumentation/core/timers.js +106 -57
  33. package/lib/instrumentation/fastify.js +1 -3
  34. package/lib/instrumentation/grpc-js/grpc.js +14 -3
  35. package/lib/instrumentation/memcached.js +5 -0
  36. package/lib/instrumentation/mongodb/common.js +88 -83
  37. package/lib/instrumentation/mongodb/v2-mongo.js +6 -3
  38. package/lib/instrumentation/mongodb.js +1 -1
  39. package/lib/instrumentation/nr-winston-transport.js +3 -4
  40. package/lib/instrumentation/redis.js +112 -88
  41. package/lib/instrumentation/undici.js +204 -190
  42. package/lib/instrumentation/{when.js → when/constants.js} +13 -10
  43. package/lib/instrumentation/when/contextualizer.js +168 -0
  44. package/lib/instrumentation/when/index.js +354 -0
  45. package/lib/instrumentation/when/nr-hooks.js +15 -0
  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/datastore-shim.js +22 -104
  58. package/lib/shim/index.js +7 -0
  59. package/lib/shim/message-shim.js +2 -0
  60. package/lib/shim/promise-shim.js +48 -42
  61. package/lib/shim/shim.js +9 -7
  62. package/lib/shim/webframework-shim.js +21 -0
  63. package/lib/spans/map-to-streaming-type.js +0 -2
  64. package/lib/spans/span-context.js +2 -0
  65. package/lib/spans/span-event-aggregator.js +2 -2
  66. package/lib/spans/span-event.js +2 -2
  67. package/lib/spans/span-streamer.js +4 -0
  68. package/lib/spans/streaming-span-event-aggregator.js +2 -4
  69. package/lib/spans/streaming-span-event.js +3 -2
  70. package/lib/symbols.js +1 -0
  71. package/lib/system-info.js +241 -166
  72. package/lib/timer.js +8 -6
  73. package/lib/transaction/dt-payload.js +4 -3
  74. package/lib/transaction/handle.js +12 -2
  75. package/lib/transaction/index.js +19 -18
  76. package/lib/transaction/name-state.js +17 -2
  77. package/lib/transaction/trace/aggregator.js +4 -12
  78. package/lib/transaction/trace/index.js +7 -5
  79. package/lib/transaction/trace/segment.js +6 -11
  80. package/lib/transaction/tracecontext.js +10 -6
  81. package/lib/transaction/tracer/index.js +23 -25
  82. package/lib/transaction/transaction-event-aggregator.js +1 -3
  83. package/lib/util/async-each-limit.js +30 -0
  84. package/lib/util/attribute-types.js +1 -2
  85. package/lib/util/attributes.js +159 -0
  86. package/lib/util/byte-limit.js +1 -3
  87. package/lib/util/cat.js +16 -13
  88. package/lib/util/code-level-metrics.js +58 -0
  89. package/lib/util/codec.js +0 -2
  90. package/lib/util/copy.js +1 -2
  91. package/lib/util/deep-equal.js +11 -137
  92. package/lib/util/flatten.js +4 -6
  93. package/lib/util/hashes.js +1 -3
  94. package/lib/util/process-version.js +2 -3
  95. package/lib/util/properties.js +2 -5
  96. package/lib/util/stream-sink.js +2 -0
  97. package/lib/util/urltils.js +4 -10
  98. package/newrelic.js +1 -1
  99. package/package.json +6 -4
  100. package/lib/instrumentation/promise.js +0 -569
package/api.js CHANGED
@@ -56,7 +56,7 @@ const CUSTOM_EVENT_TYPE_REGEX = /^[a-zA-Z0-9:_ ]+$/
56
56
  * You do not need to directly instantiate this class, as an instance of this is
57
57
  * the return from `require('newrelic')`.
58
58
  *
59
- * @param agent
59
+ * @param {object} agent Instantiation of lib/agent.js
60
60
  * @class
61
61
  */
62
62
  function API(agent) {
@@ -76,6 +76,7 @@ function API(agent) {
76
76
  *
77
77
  * @param {string} name The name you want to give the web request in the New
78
78
  * Relic UI. Will be prefixed with 'Custom/' when sent.
79
+ * @returns {void}
79
80
  */
80
81
  API.prototype.setTransactionName = function setTransactionName(name) {
81
82
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -141,8 +142,8 @@ API.prototype.getTransaction = function getTransaction() {
141
142
  * utilization.full_hostname. If utilization.full_hostname is null or empty,
142
143
  * this will be the hostname specified in the connect request as host.
143
144
  *
144
- * @param omitSupportability
145
- * @returns {LinkingMetadata} The linking object with the data above
145
+ * @param {boolean} omitSupportability Whether or not to log the supportability metric, true means skip
146
+ * @returns {object} The LinkingMetadata object with the data above
146
147
  */
147
148
  API.prototype.getLinkingMetadata = function getLinkingMetadata(omitSupportability) {
148
149
  if (omitSupportability !== true) {
@@ -205,6 +206,7 @@ API.prototype.setDispatcher = function setDispatcher(name, version) {
205
206
  * sent.
206
207
  * @param {string} action The action being invoked on the controller. Defaults
207
208
  * to the HTTP method used for the request.
209
+ * @returns {void}
208
210
  */
209
211
  API.prototype.setControllerName = function setControllerName(name, action) {
210
212
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -239,6 +241,7 @@ API.prototype.setControllerName = function setControllerName(name, action) {
239
241
  *
240
242
  * @param {string} key The key you want displayed in the RPM UI.
241
243
  * @param {string} value The value you want displayed. Must be serializable.
244
+ * @returns {false|undefined} Retruns false when disabled/errored, otherwise undefined
242
245
  */
243
246
  API.prototype.addCustomAttribute = function addCustomAttribute(key, value) {
244
247
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -294,7 +297,7 @@ API.prototype.addCustomAttribute = function addCustomAttribute(key, value) {
294
297
  *
295
298
  * newrelic.addCustomAttributes({test: 'value', test2: 'value2'});
296
299
  *
297
- * @param {object} [atts]
300
+ * @param {object} [atts] Attribute object
298
301
  * @param {string} [atts.KEY] The name you want displayed in the RPM UI.
299
302
  * @param {string} [atts.KEY.VALUE] The value you want displayed. Must be serializable.
300
303
  */
@@ -322,7 +325,7 @@ API.prototype.addCustomAttributes = function addCustomAttributes(atts) {
322
325
  *
323
326
  * newrelic.addCustomSpanAttribute({test: 'value', test2: 'value2'})
324
327
  *
325
- * @param {object} [atts]
328
+ * @param {object} [atts] Attribute object
326
329
  * @param {string} [atts.KEY] The name you want displayed in the RPM UI.API.
327
330
  * @param {string} [atts.KEY.VALUE] The value you want displayed. Must be serializable.
328
331
  */
@@ -347,6 +350,7 @@ API.prototype.addCustomSpanAttributes = function addCustomSpanAttributes(atts) {
347
350
  *
348
351
  * @param {string} key The key you want displayed in the RPM UI.
349
352
  * @param {string} value The value you want displayed. Must be serializable.
353
+ * @returns {false|undefined} Retruns false when disabled/errored, otherwise undefined
350
354
  */
351
355
  API.prototype.addCustomSpanAttribute = function addCustomSpanAttribute(key, value) {
352
356
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -386,6 +390,17 @@ API.prototype.addCustomSpanAttribute = function addCustomSpanAttribute(key, valu
386
390
  * `Error` or one of its subtypes, but the API will handle strings and objects
387
391
  * that have an attached `.message` or `.stack` property.
388
392
  *
393
+ * An example of using this function is
394
+ *
395
+ * try {
396
+ * performSomeTask();
397
+ * } catch (err) {
398
+ * newrelic.noticeError(
399
+ * err,
400
+ * {extraInformation: "error already handled in the application"}
401
+ * );
402
+ * }
403
+ *
389
404
  * NOTE: Errors that are recorded using this method do _not_ obey the
390
405
  * `ignore_status_codes` configuration.
391
406
  *
@@ -393,6 +408,7 @@ API.prototype.addCustomSpanAttribute = function addCustomSpanAttribute(key, valu
393
408
  * The error to be traced.
394
409
  * @param {object} [customAttributes]
395
410
  * Optional. Any custom attributes to be displayed in the New Relic UI.
411
+ * @returns {false|undefined} Retruns false when disabled/errored, otherwise undefined
396
412
  */
397
413
  API.prototype.noticeError = function noticeError(error, customAttributes) {
398
414
  const metric = this.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/noticeError')
@@ -534,6 +550,7 @@ API.prototype.recordLogEvent = function recordLogEvent(logEvent = {}) {
534
550
  *
535
551
  * @param {RegExp} pattern The pattern to rename (with capture groups).
536
552
  * @param {string} name The name to use for the transaction.
553
+ * @returns {void}
537
554
  */
538
555
  API.prototype.addNamingRule = function addNamingRule(pattern, name) {
539
556
  const metric = this.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/addNamingRule')
@@ -558,6 +575,7 @@ API.prototype.addNamingRule = function addNamingRule(pattern, name) {
558
575
  * newrelic.addIgnoringRule('^/socket\\.io/')
559
576
  *
560
577
  * @param {RegExp} pattern The pattern to ignore.
578
+ * @returns {void}
561
579
  */
562
580
  API.prototype.addIgnoringRule = function addIgnoringRule(pattern) {
563
581
  const metric = this.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/addIgnoringRule')
@@ -570,6 +588,52 @@ API.prototype.addIgnoringRule = function addIgnoringRule(pattern) {
570
588
  this.agent.userNormalizer.addSimple(pattern, null)
571
589
  }
572
590
 
591
+ /**
592
+ * Gracefully fail.
593
+ *
594
+ * Output an HTML comment and log a warning the comment is meant to be
595
+ * innocuous to the end user.
596
+ *
597
+ * @see RUM_ISSUES
598
+ * @param {number} errorCode Error code from `RUM_ISSUES`.
599
+ * @param {boolean} [quiet=false] Be quiet about this failure.
600
+ * @returns {string} HTML comment for debugging purposes with specific error code
601
+ */
602
+ function _gracefail(errorCode, quiet) {
603
+ if (quiet) {
604
+ logger.debug(RUM_ISSUES[errorCode])
605
+ } else {
606
+ logger.warn(RUM_ISSUES[errorCode])
607
+ }
608
+ return '<!-- NREUM: (' + errorCode + ') -->'
609
+ }
610
+
611
+ /**
612
+ * Function for generating a fully formed RUM header based on configuration options
613
+ *
614
+ * @param {object} options Configuration options for RUM
615
+ * @param {string} [options.nonce] Nonce to inject into `<script>` header.
616
+ * @param {boolean} [options.hasToRemoveScriptWrapper] Used to import agent script without `<script>` tag wrapper.
617
+ * @param {string} metadata Stringified representation of rumHash metadata
618
+ * @param {string} loader Agent Loader script
619
+ * @returns {string} fully formed RUM header
620
+ */
621
+ function _generateRUMHeader(options = {}, metadata, loader) {
622
+ const formatArgs = []
623
+
624
+ if (options.hasToRemoveScriptWrapper) {
625
+ formatArgs.push(RUM_STUB)
626
+ } else if (options.nonce) {
627
+ formatArgs.push(RUM_STUB_SHELL_WITH_NONCE_PARAM, `nonce="${options.nonce}"`)
628
+ } else {
629
+ formatArgs.push(RUM_STUB_SHELL)
630
+ }
631
+
632
+ formatArgs.push(metadata, loader)
633
+
634
+ return util.format(...formatArgs)
635
+ }
636
+
573
637
  /**
574
638
  * Get the script header necessary for Browser Monitoring
575
639
  * This script must be manually injected into your templates, as high as possible
@@ -585,9 +649,9 @@ API.prototype.addIgnoringRule = function addIgnoringRule(pattern) {
585
649
  *
586
650
  * Do *not* reuse the headers between users, or even between requests.
587
651
  *
652
+ * @param {object} options configuration options
588
653
  * @param {string} [options.nonce] - Nonce to inject into `<script>` header.
589
654
  * @param {boolean} [options.hasToRemoveScriptWrapper] - Used to import agent script without `<script>` tag wrapper.
590
- * @param options
591
655
  * @returns {string} The script content to be injected in `<head>` or put inside `<script>` tag (depending on options)
592
656
  */
593
657
  API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options) {
@@ -598,26 +662,6 @@ API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options)
598
662
 
599
663
  const config = this.agent.config
600
664
 
601
- /**
602
- * Gracefully fail.
603
- *
604
- * Output an HTML comment and log a warning the comment is meant to be
605
- * innocuous to the end user.
606
- *
607
- * @param {number} num - Error code from `RUM_ISSUES`.
608
- * @param {bool} [quite=false] - Be quiet about this failure.
609
- * @param quiet
610
- * @see RUM_ISSUES
611
- */
612
- function _gracefail(num, quiet) {
613
- if (quiet) {
614
- logger.debug(RUM_ISSUES[num])
615
- } else {
616
- logger.warn(RUM_ISSUES[num])
617
- }
618
- return '<!-- NREUM: (' + num + ') -->'
619
- }
620
-
621
665
  const browserMonitoring = config.browser_monitoring
622
666
 
623
667
  // config.browser_monitoring should always exist, but we don't want the agent
@@ -736,17 +780,7 @@ API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options)
736
780
  const json = JSON.stringify(rumHash, null, tabs)
737
781
 
738
782
  // the complete header to be written to the browser
739
- const out =
740
- options && options.hasToRemoveScriptWrapper
741
- ? util.format(RUM_STUB, json, jsAgentLoader)
742
- : options && options.nonce
743
- ? util.format(
744
- RUM_STUB_SHELL_WITH_NONCE_PARAM,
745
- 'nonce="' + options.nonce + '"',
746
- json,
747
- jsAgentLoader
748
- )
749
- : util.format(RUM_STUB_SHELL, json, jsAgentLoader)
783
+ const out = _generateRUMHeader(options, json, jsAgentLoader)
750
784
 
751
785
  logger.trace('generating RUM header', out)
752
786
 
@@ -771,7 +805,7 @@ API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options)
771
805
  * })
772
806
  * @param {string} name
773
807
  * The name to give the new segment. This will also be the name of the metric.
774
- * @param {bool} record
808
+ * @param {boolean} record
775
809
  * Indicates if the segment should be recorded as a metric. Metrics will show
776
810
  * up on the transaction breakdown table and server breakdown graph. Segments
777
811
  * just show up in transaction traces.
@@ -843,6 +877,7 @@ API.prototype.startSegment = function startSegment(name, record, handler, callba
843
877
  * so it should be a generic name and not iclude any variable parameters.
844
878
  * @param {Function} handle
845
879
  * Function that represents the transaction work.
880
+ * @returns {null|*} Returns null if handle is not a function, otherwise the return value of handle
846
881
  */
847
882
  API.prototype.startWebTransaction = function startWebTransaction(url, handle) {
848
883
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -933,7 +968,8 @@ API.prototype.startBackgroundTransaction = startBackgroundTransaction
933
968
  * https://docs.newrelic.com/docs/apm/applications-menu/monitoring/transactions-page#txn-type-dropdown
934
969
  * @param {Function} handle
935
970
  * Function that represents the background work.
936
- * @memberOf API#
971
+ * @memberof API#
972
+ * @returns {null|*} Returns null if handle is not a function, otherwise the return value of handle
937
973
  */
938
974
  function startBackgroundTransaction(name, group, handle) {
939
975
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -1038,7 +1074,7 @@ API.prototype.endTransaction = function endTransaction() {
1038
1074
  * of these keys match the names of the keys used by the platform API.
1039
1075
  *
1040
1076
  * @param {string} name The name of the metric.
1041
- * @param {number|object} value
1077
+ * @param {number|object} value The value of the metric to record
1042
1078
  */
1043
1079
  API.prototype.recordMetric = function recordMetric(name, value) {
1044
1080
  const supportMetric = this.agent.metrics.getOrCreateMetric(
@@ -1126,6 +1162,7 @@ API.prototype.incrementMetric = function incrementMetric(name, value) {
1126
1162
  * @param {object} attributes Object of key and value pairs. The keys must be shorter
1127
1163
  * than 255 characters, and the values must be string, number,
1128
1164
  * or boolean.
1165
+ * @returns {false|undefined} Returns false explicitly if failed/disabled, otherwise undefined
1129
1166
  */
1130
1167
  API.prototype.recordCustomEvent = function recordCustomEvent(eventType, attributes) {
1131
1168
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -1208,15 +1245,13 @@ API.prototype.recordCustomEvent = function recordCustomEvent(eventType, attribut
1208
1245
  * - `newrelic.instrument(moduleName, onRequire [,onError])`
1209
1246
  * - `newrelic.instrument(options)`
1210
1247
  *
1211
- * @param {object} options The options for this custom instrumentation.
1212
- * @param {string} options.moduleName The module name given to require to load the module
1213
- * @param {Function} options.onResolved The function to call prior to module load after the filepath has been resolved
1214
- * @param {Function} options.onRequire The function to call when the module has been loaded
1215
- * @param {Function} [options.onError] If provided, should `onRequire` throw an error, the error will be passed to
1216
- * this function.
1217
- * @param moduleName
1218
- * @param onRequire
1219
- * @param onError
1248
+ * @param {string|object} moduleName The module name given to require to load the module, or the instrumentation specification
1249
+ * @param {string} moduleName.moduleName The module name given to require to load the module
1250
+ * @param {Function} moduleName.onResolved The function to call prior to module load after the filepath has been resolved
1251
+ * @param {Function} moduleName.onRequire The function to call when the module has been loaded
1252
+ * @param {Function} [moduleName.onError] If provided, should `onRequire` throw an error, the error will be passed to
1253
+ * @param {Function} onRequire The function to call when the module has been loaded
1254
+ * @param {Function} onError If provided, should `onRequire` throw an error, the error will be passed to this function.
1220
1255
  */
1221
1256
  API.prototype.instrument = function instrument(moduleName, onRequire, onError) {
1222
1257
  const metric = this.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/instrument')
@@ -1241,15 +1276,13 @@ API.prototype.instrument = function instrument(moduleName, onRequire, onError) {
1241
1276
  * - `newrelic.instrumentConglomerate(moduleName, onRequire [, onError])`
1242
1277
  * - `newrelic.isntrumentConglomerate(options)`
1243
1278
  *
1244
- * @param {object} options The options for this custom instrumentation.
1245
- * @param {string} options.moduleName The module name given to require to load the module
1246
- * @param {Function} options.onResolved The function to call prior to module load after the filepath has been resolved
1247
- * @param {Function} options.onRequire The function to call when the module has been loaded
1248
- * @param {Function} [options.onError] If provided, should `onRequire` throw an error, the error will be passed to
1249
- * this function.
1250
- * @param moduleName
1251
- * @param onRequire
1252
- * @param onError
1279
+ * @param {string|object} moduleName The module name given to require to load the module, or the instrumentation specification
1280
+ * @param {string} moduleName.moduleName The module name given to require to load the module
1281
+ * @param {Function} moduleName.onResolved The function to call prior to module load after the filepath has been resolved
1282
+ * @param {Function} moduleName.onRequire The function to call when the module has been loaded
1283
+ * @param {Function} [moduleName.onError] If provided, should `onRequire` throw an error, the error will be passed to
1284
+ * @param {Function} onRequire The function to call when the module has been loaded
1285
+ * @param {Function} onError If provided, should `onRequire` throw an error, the error will be passed to this function.
1253
1286
  */
1254
1287
  API.prototype.instrumentConglomerate = function instrumentConglomerate(
1255
1288
  moduleName,
@@ -1275,15 +1308,13 @@ API.prototype.instrumentConglomerate = function instrumentConglomerate(
1275
1308
  * - `newrelic.instrumentDatastore(moduleName, onRequire [,onError])`
1276
1309
  * - `newrelic.instrumentDatastore(options)`
1277
1310
  *
1278
- * @param {object} options The options for this custom instrumentation.
1279
- * @param {string} options.moduleName The module name given to require to load the module
1280
- * @param {Function} options.onResolved The function to call prior to module load after the filepath has been resolved
1281
- * @param {Function} options.onRequire The function to call when the module has been loaded
1282
- * @param {Function} [options.onError] If provided, should `onRequire` throw an error, the error will be passed to
1283
- * this function.
1284
- * @param moduleName
1285
- * @param onRequire
1286
- * @param onError
1311
+ * @param {string|object} moduleName The module name given to require to load the module, or the instrumentation specification
1312
+ * @param {string} moduleName.moduleName The module name given to require to load the module
1313
+ * @param {Function} moduleName.onResolved The function to call prior to module load after the filepath has been resolved
1314
+ * @param {Function} moduleName.onRequire The function to call when the module has been loaded
1315
+ * @param {Function} [moduleName.onError] If provided, should `onRequire` throw an error, the error will be passed to
1316
+ * @param {Function} onRequire The function to call when the module has been loaded
1317
+ * @param {Function} onError If provided, should `onRequire` throw an error, the error will be passed to this function.
1287
1318
  */
1288
1319
  API.prototype.instrumentDatastore = function instrumentDatastore(moduleName, onRequire, onError) {
1289
1320
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -1310,15 +1341,13 @@ API.prototype.instrumentDatastore = function instrumentDatastore(moduleName, onR
1310
1341
  * - `newrelic.instrumentWebframework(moduleName, onRequire [,onError])`
1311
1342
  * - `newrelic.instrumentWebframework(options)`
1312
1343
  *
1313
- * @param {object} options The options for this custom instrumentation.
1314
- * @param {string} options.moduleName The module name given to require to load the module
1315
- * @param {Function} options.onResolved The function to call prior to module load after the filepath has been resolved
1316
- * @param {Function} options.onRequire The function to call when the module has been loaded
1317
- * @param {Function} [options.onError] If provided, should `onRequire` throw an error, the error will be passed to
1318
- * this function.
1319
- * @param moduleName
1320
- * @param onRequire
1321
- * @param onError
1344
+ * @param {string|object} moduleName The module name given to require to load the module, or the instrumentation specification
1345
+ * @param {string} moduleName.moduleName The module name given to require to load the module
1346
+ * @param {Function} moduleName.onResolved The function to call prior to module load after the filepath has been resolved
1347
+ * @param {Function} moduleName.onRequire The function to call when the module has been loaded
1348
+ * @param {Function} [moduleName.onError] If provided, should `onRequire` throw an error, the error will be passed to
1349
+ * @param {Function} onRequire The function to call when the module has been loaded
1350
+ * @param {Function} onError If provided, should `onRequire` throw an error, the error will be passed to this function.
1322
1351
  */
1323
1352
  API.prototype.instrumentWebframework = function instrumentWebframework(
1324
1353
  moduleName,
@@ -1349,15 +1378,13 @@ API.prototype.instrumentWebframework = function instrumentWebframework(
1349
1378
  * - `newrelic.instrumentMessages(moduleName, onRequire [,onError])`
1350
1379
  * - `newrelic.instrumentMessages(options)`
1351
1380
  *
1352
- * @param {object} options The options for this custom instrumentation.
1353
- * @param {string} options.moduleName The module name given to require to load the module
1354
- * @param {Function} options.onResolved The function to call prior to module load after the filepath has been resolved
1355
- * @param {Function} options.onRequire The function to call when the module has been loaded
1356
- * @param {Function} [options.onError] If provided, should `onRequire` throw an error, the error will be passed to
1357
- * this function.
1358
- * @param moduleName
1359
- * @param onRequire
1360
- * @param onError
1381
+ * @param {string|object} moduleName The module name given to require to load the module, or the instrumentation specification
1382
+ * @param {string} moduleName.moduleName The module name given to require to load the module
1383
+ * @param {Function} moduleName.onResolved The function to call prior to module load after the filepath has been resolved
1384
+ * @param {Function} moduleName.onRequire The function to call when the module has been loaded
1385
+ * @param {Function} [moduleName.onError] If provided, should `onRequire` throw an error, the error will be passed to
1386
+ * @param {Function} onRequire The function to call when the module has been loaded
1387
+ * @param {Function} onError If provided, should `onRequire` throw an error, the error will be passed to this function.
1361
1388
  */
1362
1389
  API.prototype.instrumentMessages = function instrumentMessages(moduleName, onRequire, onError) {
1363
1390
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -1396,6 +1423,7 @@ API.prototype.instrumentMessages = function instrumentMessages(moduleName, onReq
1396
1423
  * into an instrumentation key.
1397
1424
  * @param {object} module
1398
1425
  * The actual module object or function we're instrumenting
1426
+ * @returns {boolean} Whether or not the module was successfully instrumented
1399
1427
  */
1400
1428
  API.prototype.instrumentLoadedModule = function instrumentLoadedModule(moduleName, module) {
1401
1429
  const metric = this.agent.metrics.getOrCreateMetric(
@@ -1456,9 +1484,8 @@ API.prototype.getTraceMetadata = function getTraceMetadata() {
1456
1484
  * Time in milliseconds to wait before shutting down.
1457
1485
  * @param {boolean} [options.waitForIdle=false]
1458
1486
  * If true, the agent will not shut down until there are no active transactions.
1459
- * @param {Function} [callback]
1487
+ * @param {Function} [cb]
1460
1488
  * Callback function that runs when agent stops.
1461
- * @param cb
1462
1489
  */
1463
1490
  API.prototype.shutdown = function shutdown(options, cb) {
1464
1491
  this.agent.metrics.getOrCreateMetric(`${NAMES.SUPPORTABILITY.API}/shutdown`).incrementCallCount()
@@ -1481,9 +1508,31 @@ API.prototype.shutdown = function shutdown(options, cb) {
1481
1508
  }
1482
1509
 
1483
1510
  /**
1484
- * @param api
1485
- * @param options
1486
- * @param callback
1511
+ * Helper function for logging if an error occurs, and where
1512
+ *
1513
+ * @param {Error} error If defined, the error that occurred
1514
+ * @param {string} phase Where in the process the error happened
1515
+ * @returns {void}
1516
+ */
1517
+ function _logErrorCallback(error, phase) {
1518
+ if (error) {
1519
+ logger.error(error, `An error occurred during ${phase}`)
1520
+ }
1521
+ }
1522
+
1523
+ /**
1524
+ * Function for handling the graceful shutdown process, including processing of data and handling errors
1525
+ *
1526
+ * @param {object} api instantiation of this file
1527
+ * @param {object} options shutdown options object
1528
+ * @param {boolean} [options.collectPendingData=false]
1529
+ * If true, the agent will send any pending data to the collector before
1530
+ * shutting down.
1531
+ * @param {number} [options.timeout=0]
1532
+ * Time in milliseconds to wait before shutting down.
1533
+ * @param {boolean} [options.waitForIdle=false]
1534
+ * If true, the agent will not shut down until there are no active transactions.
1535
+ * @param {Function} callback callback function to execute after shutdown process is complete (successful or not)
1487
1536
  */
1488
1537
  function _doShutdown(api, options, callback) {
1489
1538
  const agent = api.agent
@@ -1501,12 +1550,12 @@ function _doShutdown(api, options, callback) {
1501
1550
  }
1502
1551
 
1503
1552
  /**
1504
- * @param error
1553
+ * Callback function for after harvest cycles happen as part of shutdown process
1554
+ *
1555
+ * @param {Error} error If defined, the error that occurred during harvest
1505
1556
  */
1506
1557
  function afterHarvest(error) {
1507
- if (error) {
1508
- logger.error(error, 'An error occurred while running last harvest before shutdown.')
1509
- }
1558
+ _logErrorCallback(error, 'last harvest before shutdown')
1510
1559
  agent.stop(callback)
1511
1560
  }
1512
1561
 
@@ -1524,10 +1573,8 @@ function _doShutdown(api, options, callback) {
1524
1573
  })
1525
1574
 
1526
1575
  agent.on('errored', function logShutdownError(error) {
1576
+ _logErrorCallback(error, 'after shutdown')
1527
1577
  agent.stop(callback)
1528
- if (error) {
1529
- logger.error(error, 'The agent encountered an error after calling shutdown.')
1530
- }
1531
1578
  })
1532
1579
  } else if (options.collectPendingData) {
1533
1580
  agent.forceHarvestAll(afterHarvest)
@@ -1537,8 +1584,12 @@ function _doShutdown(api, options, callback) {
1537
1584
  }
1538
1585
 
1539
1586
  /**
1540
- * @param object
1541
- * @param maxLength
1587
+ * Validates that all keys in a given object have values that are less than or equal to a given length
1588
+ * Assumes all values have .length property (string/array)
1589
+ *
1590
+ * @param {object} object The object to validate
1591
+ * @param {number} maxLength The max allowed length
1592
+ * @returns {boolean} Whether or not the object passes validation
1542
1593
  */
1543
1594
  function _checkKeyLength(object, maxLength) {
1544
1595
  const keys = Object.keys(object)
@@ -1569,8 +1620,11 @@ API.prototype.setLambdaHandler = function setLambdaHandler(handler) {
1569
1620
  }
1570
1621
 
1571
1622
  /**
1572
- * @param attributes
1573
- * @param name
1623
+ * Function for removing invalid attribute key/value pairs from an object
1624
+ *
1625
+ * @param {object} attributes The attribute object
1626
+ * @param {string} name Caller name, used for debugging/logging purposes only
1627
+ * @returns {object} Attribute object containing only valid key/value pairs
1574
1628
  */
1575
1629
  function _filterAttributes(attributes, name) {
1576
1630
  const filteredAttributes = Object.create(null)
@@ -64,7 +64,7 @@ function run(opts) {
64
64
  let appliedRules = []
65
65
 
66
66
  // responsible for handling default rules provided by the server
67
- const defaultNormalizer = loadDefaultNormalizer(config, runtimeRules)
67
+ const defaultNormalizer = loadDefaultNormalizer(config)
68
68
 
69
69
  // rules defined by user in local configuration file
70
70
  const userNormalizer = loadUserNormalizer(config, runtimeRules)
package/esm-loader.mjs CHANGED
@@ -197,11 +197,9 @@ async function wrapEsmSource(url, specifier) {
197
197
  const _wrappedModule = wrapModule(_originalModule, '${specifier}', '${trimmedUrl}')
198
198
  ${props
199
199
  .map((propName) => {
200
- const propertyExportSource = `
200
+ return `
201
201
  let _${propName} = _wrappedModule.${propName}
202
202
  export { _${propName} as ${propName} }`
203
-
204
- return propertyExportSource
205
203
  })
206
204
  .join('\n')}
207
205
  `
@@ -79,8 +79,7 @@ class AdaptiveSampler {
79
79
  * the number of objects sampled in this window.
80
80
  *
81
81
  * @param {number} roll - The number to compare against the threshold
82
- *
83
- * @return {bool} True if the object should be sampled.
82
+ * @returns {bool} True if the object should be sampled.
84
83
  */
85
84
  shouldSample(roll) {
86
85
  ++this._seen