newrelic 9.7.0 → 9.7.2

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 (37) hide show
  1. package/NEWS.md +42 -18
  2. package/THIRD_PARTY_NOTICES.md +203 -2
  3. package/api.js +155 -103
  4. package/lib/agent.js +29 -82
  5. package/lib/collector/api.js +234 -201
  6. package/lib/config/attribute-filter.js +35 -25
  7. package/lib/config/default.js +45 -19
  8. package/lib/config/index.js +260 -199
  9. package/lib/environment.js +16 -12
  10. package/lib/errors/error-collector.js +124 -55
  11. package/lib/errors/index.js +59 -49
  12. package/lib/instrumentation/@hapi/hapi.js +56 -50
  13. package/lib/instrumentation/@node-redis/client.js +50 -41
  14. package/lib/instrumentation/amqplib.js +116 -151
  15. package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -11
  16. package/lib/instrumentation/core/globals.js +1 -1
  17. package/lib/instrumentation/core/http-outbound.js +193 -78
  18. package/lib/instrumentation/core/timers.js +106 -59
  19. package/lib/instrumentation/grpc-js/grpc.js +20 -23
  20. package/lib/instrumentation/mongodb/common.js +87 -85
  21. package/lib/instrumentation/redis.js +112 -90
  22. package/lib/instrumentation/undici.js +204 -192
  23. package/lib/instrumentation/{when.js → when/constants.js} +13 -10
  24. package/lib/instrumentation/when/contextualizer.js +168 -0
  25. package/lib/instrumentation/when/index.js +354 -0
  26. package/lib/instrumentation/when/nr-hooks.js +15 -0
  27. package/lib/instrumentations.js +1 -1
  28. package/lib/shim/shim.js +2 -0
  29. package/lib/shim/webframework-shim.js +19 -0
  30. package/lib/symbols.js +1 -0
  31. package/lib/system-info.js +240 -163
  32. package/lib/util/async-each-limit.js +30 -0
  33. package/lib/util/attributes.js +159 -0
  34. package/lib/util/code-level-metrics.js +58 -0
  35. package/lib/util/deep-equal.js +11 -144
  36. package/package.json +5 -4
  37. package/lib/instrumentation/promise.js +0 -572
package/lib/agent.js CHANGED
@@ -5,8 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- /* eslint sonarjs/cognitive-complexity: ["error", 23] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
-
10
8
  const AdaptiveSampler = require('./adaptive-sampler')
11
9
  const CollectorAPI = require('./collector/api')
12
10
  const ServerlessCollector = require('./collector/serverless')
@@ -16,7 +14,6 @@ const ErrorCollector = require('./errors/error-collector')
16
14
  const ErrorTraceAggregator = require('./errors/error-trace-aggregator')
17
15
  const ErrorEventAggregator = require('./errors/error-event-aggregator')
18
16
  const EventEmitter = require('events').EventEmitter
19
- const hashes = require('./util/hashes')
20
17
  const logger = require('./logger')
21
18
  const LogAggregator = require('./aggregators/log-aggregator')
22
19
  const MetricMapper = require('./metrics/mapper')
@@ -33,6 +30,15 @@ const uninstrumented = require('./uninstrumented')
33
30
  const util = require('util')
34
31
  const createSpanEventAggregator = require('./spans/create-span-event-aggregator')
35
32
  const createContextManager = require('./context-manager/create-context-manager')
33
+ const {
34
+ maybeAddDatabaseAttributes,
35
+ maybeAddExternalAttributes,
36
+ addRequiredCATAttributes,
37
+ maybeAddExtraCATAttributes,
38
+ maybeAddParentAttributes,
39
+ maybeAddQueueAttributes,
40
+ maybeAddSyntheticAttributes
41
+ } = require('./util/attributes')
36
42
 
37
43
  // Map of valid states to whether or not data collection is valid
38
44
  const STATES = {
@@ -58,7 +64,7 @@ const DEFAULT_HARVEST_INTERVAL_MS = 60000
58
64
  * available. Don't try to recover here, because without configuration the
59
65
  * agent can't be brought up to a useful state.
60
66
  *
61
- * @param config
67
+ * @param {object} config Agent configuration object
62
68
  */
63
69
  function Agent(config) {
64
70
  EventEmitter.call(this)
@@ -201,8 +207,8 @@ util.inherits(Agent, EventEmitter)
201
207
  * managed by index.js. An agent will be created even if the agent's disabled by
202
208
  * the configuration.
203
209
  *
204
- * @config {boolean} agent_enabled Whether to start up the agent.
205
210
  * @param {Function} callback Continuation and error handler.
211
+ * @returns {void}
206
212
  */
207
213
  Agent.prototype.start = function start(callback) {
208
214
  if (!callback) {
@@ -456,8 +462,8 @@ Agent.prototype.startAggregators = function startAggregators() {
456
462
  * Completes any final setup upon full connection to New Relic
457
463
  * servers and sets the agent state to 'started'.
458
464
  *
459
- * @param shouldImmediatelyHarvest
460
- * @param callback
465
+ * @param {boolean} shouldImmediatelyHarvest Whether we should immediately schedule a harvest, or wait a cycle
466
+ * @param {Function} callback callback function that executes after harvest completes (now if immediate, otherwise later)
461
467
  */
462
468
  Agent.prototype.onConnect = function onConnect(shouldImmediatelyHarvest, callback) {
463
469
  this._reconfigureAggregators(this.config)
@@ -516,7 +522,7 @@ Agent.prototype._scheduleHarvests = function _scheduleHarvests(shouldImmediately
516
522
  * Bypasses standard collector connection by immediately invoking the startup
517
523
  * callback, after gathering local environment details.
518
524
  *
519
- * @param {Function} callback
525
+ * @param {Function} callback Immediately invoked callback
520
526
  */
521
527
  Agent.prototype._serverlessModeStart = function _serverlessModeStart(callback) {
522
528
  logger.info('New Relic for Node.js starting in serverless mode -- skipping connection process.')
@@ -531,7 +537,7 @@ Agent.prototype._serverlessModeStart = function _serverlessModeStart(callback) {
531
537
  * "hard" restart. This requires working with shimmer to strip the
532
538
  * current instrumentation and patch to the module loader.
533
539
  *
534
- * @param callback
540
+ * @param {Function} callback callback function to invoke after agent stop
535
541
  */
536
542
  Agent.prototype.stop = function stop(callback) {
537
543
  if (!callback) {
@@ -589,9 +595,6 @@ Agent.prototype._resetEvents = function resetEvents() {
589
595
 
590
596
  /**
591
597
  * Resets custom events.
592
- *
593
- * @param {boolean} forceReset
594
- * Flag signalling unconditional reset, sent during LASP application.
595
598
  */
596
599
  Agent.prototype._resetCustomEvents = function resetCustomEvents() {
597
600
  this.customEventAggregator.clear()
@@ -698,6 +701,8 @@ Agent.prototype.setState = function setState(newState) {
698
701
  /**
699
702
  * Return true if the agent is in a run state that can collect and
700
703
  * process data.
704
+ *
705
+ * @returns {boolean} Whether or not the agent can collect data in its current state
701
706
  */
702
707
  Agent.prototype.canCollectData = function canCollectData() {
703
708
  return STATES[this._state]
@@ -737,84 +742,26 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
737
742
  error: transaction.hasErrors()
738
743
  }
739
744
 
740
- let metric = transaction.metrics.getMetric(NAMES.QUEUETIME)
741
- if (metric) {
742
- intrinsicAttributes.queueDuration = metric.total
743
- }
744
-
745
- metric = transaction.metrics.getMetric(NAMES.EXTERNAL.ALL)
746
- if (metric) {
747
- intrinsicAttributes.externalDuration = metric.total
748
- intrinsicAttributes.externalCallCount = metric.callCount
749
- }
750
-
751
- metric = transaction.metrics.getMetric(NAMES.DB.ALL)
752
- if (metric) {
753
- intrinsicAttributes.databaseDuration = metric.total
754
- intrinsicAttributes.databaseCallCount = metric.callCount
755
- }
745
+ maybeAddQueueAttributes(transaction, intrinsicAttributes)
746
+ maybeAddExternalAttributes(transaction, intrinsicAttributes)
747
+ maybeAddDatabaseAttributes(transaction, intrinsicAttributes)
748
+ maybeAddSyntheticAttributes(transaction, intrinsicAttributes)
756
749
 
757
750
  if (this.config.distributed_tracing.enabled) {
758
751
  transaction.addDistributedTraceIntrinsics(intrinsicAttributes)
759
- if (transaction.parentSpanId) {
760
- intrinsicAttributes.parentSpanId = transaction.parentSpanId
761
- }
762
-
763
- if (transaction.parentId) {
764
- intrinsicAttributes.parentId = transaction.parentId
765
- }
752
+ maybeAddParentAttributes(transaction, intrinsicAttributes)
766
753
  } else if (
767
754
  this.config.cross_application_tracer.enabled &&
768
755
  !transaction.invalidIncomingExternalTransaction &&
769
756
  (transaction.referringTransactionGuid || transaction.includesOutboundRequests())
770
757
  ) {
771
- intrinsicAttributes['nr.guid'] = transaction.id
772
- intrinsicAttributes['nr.tripId'] = transaction.tripId || transaction.id
773
- intrinsicAttributes['nr.pathHash'] = hashes.calculatePathHash(
774
- this.config.applications()[0],
775
- transaction.getFullName(),
776
- transaction.referringPathHash
777
- )
778
- if (transaction.referringPathHash) {
779
- intrinsicAttributes['nr.referringPathHash'] = transaction.referringPathHash
780
- }
781
- if (transaction.referringTransactionGuid) {
782
- const refId = transaction.referringTransactionGuid
783
- intrinsicAttributes['nr.referringTransactionGuid'] = refId
784
- }
785
- const alternatePathHashes = transaction.alternatePathHashes()
786
- if (alternatePathHashes) {
787
- intrinsicAttributes['nr.alternatePathHashes'] = alternatePathHashes
788
- }
789
- if (transaction.baseSegment && transaction.type === 'web') {
790
- const apdex =
791
- this.config.web_transactions_apdex[transaction.getFullName()] || this.config.apdex_t
792
- const duration = transaction.baseSegment.getDurationInMillis() / 1000
793
- intrinsicAttributes['nr.apdexPerfZone'] = calculateApdexZone(duration, apdex)
794
- }
795
- }
796
-
797
- if (transaction.syntheticsData) {
798
- intrinsicAttributes['nr.syntheticsResourceId'] = transaction.syntheticsData.resourceId
799
- intrinsicAttributes['nr.syntheticsJobId'] = transaction.syntheticsData.jobId
800
- intrinsicAttributes['nr.syntheticsMonitorId'] = transaction.syntheticsData.monitorId
758
+ addRequiredCATAttributes(transaction, intrinsicAttributes, this.config)
759
+ maybeAddExtraCATAttributes(transaction, intrinsicAttributes, this.config)
801
760
  }
802
761
 
803
762
  return intrinsicAttributes
804
763
  }
805
764
 
806
- function calculateApdexZone(duration, apdexT) {
807
- if (duration <= apdexT) {
808
- return 'S' // satisfied
809
- }
810
-
811
- if (duration <= apdexT * 4) {
812
- return 'T' // tolerating
813
- }
814
-
815
- return 'F' // frustrated
816
- }
817
-
818
765
  Agent.prototype._addEventFromTransaction = function _addEventFromTransaction(tx) {
819
766
  if (!this.config.transaction_events.enabled) {
820
767
  return
@@ -833,7 +780,7 @@ Agent.prototype._addEventFromTransaction = function _addEventFromTransaction(tx)
833
780
  * Put all the logic for handing finalized transactions off to the tracers and
834
781
  * metric collections in one place.
835
782
  *
836
- * @param {Transaction} transaction Newly-finalized transaction.
783
+ * @param {object} transaction Newly-finalized transaction.
837
784
  */
838
785
  Agent.prototype._transactionFinished = function _transactionFinished(transaction) {
839
786
  // Allow the API to explicitly set the ignored status.
@@ -881,7 +828,7 @@ Agent.prototype.setLambdaFunctionVersion = function setLambdaFunctionVersion(fun
881
828
  /**
882
829
  * Get the current transaction (if there is one) from the tracer.
883
830
  *
884
- * @returns {Transaction} The current transaction.
831
+ * @returns {object} The current transaction.
885
832
  */
886
833
  Agent.prototype.getTransaction = function getTransaction() {
887
834
  return this.tracer.getTransaction()
@@ -938,7 +885,7 @@ Agent.prototype._listenForConfigChanges = function _listenForConfigChanges() {
938
885
  * utilization.full_hostname. If utilization.full_hostname is null or empty,
939
886
  * this will be the hostname specified in the connect request as host.
940
887
  *
941
- * @returns {LinkingMetadata} The linking object with the data above
888
+ * @returns {object} The LinkingMetadata object with the data above
942
889
  */
943
890
  Agent.prototype.getLinkingMetadata = function getLinkingMetadata() {
944
891
  const segment = this.tracer.getSegment()
@@ -988,7 +935,7 @@ Agent.prototype.getNRLinkingMetadata = function getNRLinkingMetadata() {
988
935
  * Retries value for a given key but defaults to `` if falsey
989
936
  *
990
937
  * @param {string} key in linking metadata
991
- * @returns {string}
938
+ * @returns {string} Metadata value or empty string
992
939
  */
993
940
  function getValue(key) {
994
941
  return metadata[key] || ''
@@ -1039,7 +986,7 @@ function generateEventHarvestSupportMetrics(agent, harvestConfig) {
1039
986
  * Increments the call counts of application logging supportability metrics
1040
987
  * on every connect cycle
1041
988
  *
1042
- * @param {Agent} agent
989
+ * @param {object} agent Instantiation of Node.js agent
1043
990
  */
1044
991
  function generateLoggingSupportMetrics(agent) {
1045
992
  const loggingConfig = agent.config.application_logging