newrelic 8.0.0 → 8.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/NEWS.md +5023 -4922
  2. package/THIRD_PARTY_NOTICES.md +618 -209
  3. package/api.js +156 -219
  4. package/bin/test-naming-rules.js +57 -51
  5. package/bin/tracetractor +0 -1
  6. package/index.js +7 -14
  7. package/lib/agent.js +111 -114
  8. package/lib/aggregators/base-aggregator.js +1 -1
  9. package/lib/aggregators/event-aggregator.js +6 -6
  10. package/lib/attributes.js +13 -14
  11. package/lib/collector/api.js +44 -54
  12. package/lib/collector/facts.js +68 -66
  13. package/lib/collector/http-agents.js +36 -32
  14. package/lib/collector/key-parser.js +1 -1
  15. package/lib/collector/parse-response.js +1 -2
  16. package/lib/collector/remote-method.js +69 -61
  17. package/lib/collector/serverless.js +13 -18
  18. package/lib/collector/ssl/certificates.js +1056 -1056
  19. package/lib/config/attribute-filter.js +109 -101
  20. package/lib/config/default.js +35 -21
  21. package/lib/config/env.js +17 -12
  22. package/lib/config/harvest-config-validator.js +1 -1
  23. package/lib/config/hsm.js +1 -1
  24. package/lib/config/index.js +240 -234
  25. package/lib/config/lasp.js +3 -3
  26. package/lib/config/merge-server-config.js +8 -6
  27. package/lib/custom-events/custom-event-aggregator.js +1 -1
  28. package/lib/db/parse-sql.js +13 -16
  29. package/lib/db/parsed-statement.js +13 -19
  30. package/lib/db/query-parsers/sql.js +12 -15
  31. package/lib/db/query-sample.js +16 -12
  32. package/lib/db/query-trace-aggregator.js +16 -16
  33. package/lib/db/statement-matcher.js +5 -5
  34. package/lib/db/utils.js +2 -2
  35. package/lib/environment.js +210 -175
  36. package/lib/errors/error-collector.js +20 -33
  37. package/lib/errors/error-event-aggregator.js +1 -1
  38. package/lib/errors/error-trace-aggregator.js +3 -4
  39. package/lib/errors/helper.js +23 -32
  40. package/lib/errors/index.js +31 -43
  41. package/lib/feature_flags.js +3 -4
  42. package/lib/grpc/connection/states.js +6 -6
  43. package/lib/grpc/connection.js +35 -46
  44. package/lib/header-attributes.js +55 -59
  45. package/lib/header-processing.js +1 -1
  46. package/lib/instrumentation/amqplib.js +34 -43
  47. package/lib/instrumentation/bluebird.js +63 -22
  48. package/lib/instrumentation/cassandra-driver.js +8 -4
  49. package/lib/instrumentation/connect.js +7 -6
  50. package/lib/instrumentation/core/async_hooks.js +16 -9
  51. package/lib/instrumentation/core/child_process.js +20 -28
  52. package/lib/instrumentation/core/crypto.js +1 -7
  53. package/lib/instrumentation/core/dns.js +3 -7
  54. package/lib/instrumentation/core/domain.js +4 -10
  55. package/lib/instrumentation/core/fs.js +22 -37
  56. package/lib/instrumentation/core/globals.js +4 -8
  57. package/lib/instrumentation/core/http-outbound.js +20 -114
  58. package/lib/instrumentation/core/http.js +61 -128
  59. package/lib/instrumentation/core/inspector.js +7 -11
  60. package/lib/instrumentation/core/net.js +3 -1
  61. package/lib/instrumentation/core/timers.js +21 -28
  62. package/lib/instrumentation/core/zlib.js +3 -11
  63. package/lib/instrumentation/director.js +4 -4
  64. package/lib/instrumentation/express.js +12 -10
  65. package/lib/instrumentation/fastify/spec-builders.js +5 -0
  66. package/lib/instrumentation/fastify.js +37 -10
  67. package/lib/instrumentation/generic-pool.js +1 -1
  68. package/lib/instrumentation/hapi/hapi-17.js +20 -21
  69. package/lib/instrumentation/hapi/shared.js +1 -1
  70. package/lib/instrumentation/hapi.js +37 -37
  71. package/lib/instrumentation/ioredis.js +8 -9
  72. package/lib/instrumentation/memcached.js +41 -45
  73. package/lib/instrumentation/mongodb/common.js +221 -0
  74. package/lib/instrumentation/mongodb/constants.js +87 -0
  75. package/lib/instrumentation/mongodb/v2-mongo.js +110 -0
  76. package/lib/instrumentation/mongodb/v3-mongo.js +80 -0
  77. package/lib/instrumentation/mongodb/v4-mongo.js +90 -0
  78. package/lib/instrumentation/mongodb.js +20 -312
  79. package/lib/instrumentation/mysql.js +51 -44
  80. package/lib/instrumentation/oracle.js +24 -28
  81. package/lib/instrumentation/pg.js +34 -25
  82. package/lib/instrumentation/promise.js +65 -62
  83. package/lib/instrumentation/q.js +2 -2
  84. package/lib/instrumentation/redis.js +38 -38
  85. package/lib/instrumentation/restify.js +1 -1
  86. package/lib/instrumentation/vision.js +4 -4
  87. package/lib/instrumentation/when.js +12 -4
  88. package/lib/instrumentations.js +25 -25
  89. package/lib/logger.js +6 -6
  90. package/lib/metrics/index.js +50 -30
  91. package/lib/metrics/mapper.js +15 -15
  92. package/lib/metrics/metric-aggregator.js +5 -10
  93. package/lib/metrics/names.js +8 -7
  94. package/lib/metrics/normalizer/rule.js +14 -15
  95. package/lib/metrics/normalizer/tx_segment.js +33 -29
  96. package/lib/metrics/normalizer.js +51 -54
  97. package/lib/metrics/recorders/custom.js +8 -6
  98. package/lib/metrics/recorders/distributed-trace.js +3 -18
  99. package/lib/metrics/recorders/generic.js +6 -5
  100. package/lib/metrics/recorders/http.js +11 -13
  101. package/lib/metrics/recorders/http_external.js +8 -10
  102. package/lib/metrics/recorders/message-transaction.js +7 -18
  103. package/lib/metrics/recorders/other.js +7 -17
  104. package/lib/parse-proc-cpuinfo.js +26 -31
  105. package/lib/parse-proc-meminfo.js +5 -3
  106. package/lib/prioritized-attributes.js +14 -19
  107. package/lib/priority-queue.js +11 -11
  108. package/lib/proxy/grpc.js +1 -1
  109. package/lib/reservoir.js +12 -6
  110. package/lib/sampler.js +33 -34
  111. package/lib/serverless/api-gateway.js +3 -3
  112. package/lib/serverless/aws-lambda.js +28 -37
  113. package/lib/shim/conglomerate-shim.js +4 -4
  114. package/lib/shim/datastore-shim.js +61 -67
  115. package/lib/shim/index.js +10 -11
  116. package/lib/shim/message-shim.js +149 -151
  117. package/lib/shim/promise-shim.js +19 -14
  118. package/lib/shim/shim.js +131 -125
  119. package/lib/shim/specs/index.js +21 -22
  120. package/lib/shim/transaction-shim.js +52 -210
  121. package/lib/shim/webframework-shim.js +75 -85
  122. package/lib/shimmer.js +184 -166
  123. package/lib/spans/create-span-event-aggregator.js +11 -8
  124. package/lib/spans/span-context.js +4 -10
  125. package/lib/spans/span-event-aggregator.js +68 -13
  126. package/lib/spans/span-event.js +6 -8
  127. package/lib/spans/span-streamer.js +10 -18
  128. package/lib/spans/streaming-span-attributes.js +1 -1
  129. package/lib/spans/streaming-span-event-aggregator.js +1 -1
  130. package/lib/spans/streaming-span-event.js +4 -4
  131. package/lib/stats/apdex.js +7 -13
  132. package/lib/stats/index.js +14 -19
  133. package/lib/system-info.js +29 -25
  134. package/lib/timer.js +35 -21
  135. package/lib/transaction/dt-payload.js +1 -1
  136. package/lib/transaction/handle.js +19 -19
  137. package/lib/transaction/index.js +133 -151
  138. package/lib/transaction/name-state.js +18 -19
  139. package/lib/transaction/trace/aggregator.js +78 -73
  140. package/lib/transaction/trace/exclusive-time-calculator.js +9 -13
  141. package/lib/transaction/trace/index.js +37 -35
  142. package/lib/transaction/trace/segment.js +56 -73
  143. package/lib/transaction/tracecontext.js +38 -46
  144. package/lib/transaction/tracer/index.js +130 -91
  145. package/lib/transaction/transaction-event-aggregator.js +29 -31
  146. package/lib/uninstrumented.js +11 -12
  147. package/lib/util/arity.js +2 -2
  148. package/lib/util/attribute-types.js +1 -5
  149. package/lib/util/byte-limit.js +4 -5
  150. package/lib/util/cat.js +270 -33
  151. package/lib/util/codec.js +10 -6
  152. package/lib/util/copy.js +2 -2
  153. package/lib/util/deep-equal.js +51 -21
  154. package/lib/util/flatten.js +9 -6
  155. package/lib/util/hashes.js +16 -16
  156. package/lib/util/label-parser.js +22 -28
  157. package/lib/util/logger.js +53 -35
  158. package/lib/util/process-version.js +3 -3
  159. package/lib/util/properties.js +5 -5
  160. package/lib/util/sql/obfuscate.js +21 -31
  161. package/lib/util/stream-sink.js +5 -6
  162. package/lib/util/unwrapped-core.js +2 -2
  163. package/lib/util/urltils.js +26 -30
  164. package/lib/utilization/aws-info.js +8 -9
  165. package/lib/utilization/azure-info.js +37 -35
  166. package/lib/utilization/common.js +17 -16
  167. package/lib/utilization/docker-info.js +14 -16
  168. package/lib/utilization/gcp-info.js +38 -37
  169. package/lib/utilization/index.js +5 -5
  170. package/lib/utilization/kubernetes-info.js +2 -2
  171. package/lib/utilization/pcf-info.js +12 -12
  172. package/package.json +23 -6
  173. package/stub_api.js +16 -14
@@ -1,5 +1,4 @@
1
1
  #! /usr/bin/env node
2
-
3
2
  /*
4
3
  * Copyright 2020 New Relic Corporation. All rights reserved.
5
4
  * SPDX-License-Identifier: Apache-2.0
@@ -8,18 +7,18 @@
8
7
  'use strict'
9
8
  /* eslint-disable no-console */
10
9
 
11
- var fs = require('fs')
12
- var path = require('path')
13
- var readline = require('readline')
14
- var urltils = require('../lib/util/urltils')
15
- var MetricNormalizer = require('../lib/metrics/normalizer')
10
+ const fs = require('fs')
11
+ const path = require('path')
12
+ const readline = require('readline')
13
+ const urltils = require('../lib/util/urltils')
14
+ const MetricNormalizer = require('../lib/metrics/normalizer')
16
15
 
17
- var cwd = process.cwd()
18
- var options = null
16
+ const cwd = process.cwd()
17
+ let options = null
19
18
  if (arrayContainsAny(process.argv, '-h', '-?', '--help')) {
20
19
  printHelp()
21
20
  } else if (process.argv.length === 3) {
22
- options = {rules: null, urls: path.resolve(cwd, process.argv[2])}
21
+ options = { rules: null, urls: path.resolve(cwd, process.argv[2]) }
23
22
  } else if (process.argv.length === 4) {
24
23
  options = {
25
24
  rules: path.resolve(cwd, process.argv[2]),
@@ -60,26 +59,26 @@ function printHelp() {
60
59
  }
61
60
 
62
61
  function run(opts) {
63
- var config = require('../lib/config').initialize()
64
- var runtimeRules = opts.rules ? require(opts.rules) : null
65
- var appliedRules = []
62
+ const config = require('../lib/config').initialize()
63
+ const runtimeRules = opts.rules ? require(opts.rules) : null
64
+ let appliedRules = []
66
65
 
67
66
  // responsible for handling default rules provided by the server
68
- var defaultNormalizer = loadDefaultNormalizer(config, runtimeRules)
67
+ const defaultNormalizer = loadDefaultNormalizer(config, runtimeRules)
69
68
 
70
69
  // rules defined by user in local configuration file
71
- var userNormalizer = loadUserNormalizer(config, runtimeRules)
70
+ const userNormalizer = loadUserNormalizer(config, runtimeRules)
72
71
 
73
72
  defaultNormalizer.on('appliedRule', onAppliedRule)
74
73
  userNormalizer.on('appliedRule', onAppliedRule)
75
74
 
76
- var urlsFile = fs.createReadStream(opts.urls, {encoding: 'utf-8'})
77
- var reader = readline.createInterface({input: urlsFile, output: null})
75
+ const urlsFile = fs.createReadStream(opts.urls, { encoding: 'utf-8' })
76
+ const reader = readline.createInterface({ input: urlsFile, output: null })
78
77
  reader.on('line', function onUrlLine(urlLine) {
79
78
  appliedRules = []
80
- var scrubbedUrl = urltils.scrub(urlLine)
79
+ const scrubbedUrl = urltils.scrub(urlLine)
81
80
 
82
- var normalized = userNormalizer.normalize(scrubbedUrl)
81
+ let normalized = userNormalizer.normalize(scrubbedUrl)
83
82
 
84
83
  if (!normalized.matched) {
85
84
  normalized = defaultNormalizer.normalize(scrubbedUrl)
@@ -89,11 +88,14 @@ function run(opts) {
89
88
  if (appliedRules.length === 0) {
90
89
  console.log('no rules matched')
91
90
  } else {
92
- for (var i = 0; i < appliedRules.length; i++) {
93
- var match = appliedRules[i]
91
+ for (let i = 0; i < appliedRules.length; i++) {
92
+ const match = appliedRules[i]
94
93
  console.log(
95
94
  ' %s: %s => %s (rule %s)',
96
- (i + 1), match.original, match.normalized, match.rule.pattern
95
+ i + 1,
96
+ match.original,
97
+ match.normalized,
98
+ match.rule.pattern
97
99
  )
98
100
  }
99
101
  }
@@ -117,43 +119,47 @@ function run(opts) {
117
119
 
118
120
  function loadDefaultNormalizer(config) {
119
121
  // Load the normalizer.
120
- var normalizer = new MetricNormalizer(config, 'URL')
122
+ const normalizer = new MetricNormalizer(config, 'URL')
121
123
 
122
124
  // Add in the rules the collector would ship down.
123
- normalizer.load([{
124
- 'match_expression':
125
- '.*\\.(ace|arj|ini|txt|udl|plist|css|gif|ico|jpe?g|js|png|swf|woff|caf|' +
126
- 'aiff|m4v|mpe?g|mp3|mp4|mov)$',
127
- 'replacement': '/*.\\1',
128
- 'replace_all': false,
129
- 'each_segment': false,
130
- 'ignore': false,
131
- 'terminate_chain': true,
132
- 'eval_order': 1000
133
- }, {
134
- 'match_expression': '^[0-9][0-9a-f_,.-]*$',
135
- 'replacement': '*',
136
- 'replace_all': false,
137
- 'each_segment': true,
138
- 'ignore': false,
139
- 'terminate_chain': false,
140
- 'eval_order': 1001
141
- }, {
142
- 'match_expression': '^(.*)/[0-9][0-9a-f_,-]*\\.([0-9a-z][0-9a-z]*)$',
143
- 'replacement': '\\1/.*\\2',
144
- 'replace_all': false,
145
- 'each_segment': false,
146
- 'ignore': false,
147
- 'terminate_chain': false,
148
- 'eval_order': 1002
149
- }])
125
+ normalizer.load([
126
+ {
127
+ match_expression:
128
+ '.*\\.(ace|arj|ini|txt|udl|plist|css|gif|ico|jpe?g|js|png|swf|woff|caf|' +
129
+ 'aiff|m4v|mpe?g|mp3|mp4|mov)$',
130
+ replacement: '/*.\\1',
131
+ replace_all: false,
132
+ each_segment: false,
133
+ ignore: false,
134
+ terminate_chain: true,
135
+ eval_order: 1000
136
+ },
137
+ {
138
+ match_expression: '^[0-9][0-9a-f_,.-]*$',
139
+ replacement: '*',
140
+ replace_all: false,
141
+ each_segment: true,
142
+ ignore: false,
143
+ terminate_chain: false,
144
+ eval_order: 1001
145
+ },
146
+ {
147
+ match_expression: '^(.*)/[0-9][0-9a-f_,-]*\\.([0-9a-z][0-9a-z]*)$',
148
+ replacement: '\\1/.*\\2',
149
+ replace_all: false,
150
+ each_segment: false,
151
+ ignore: false,
152
+ terminate_chain: false,
153
+ eval_order: 1002
154
+ }
155
+ ])
150
156
 
151
157
  return normalizer
152
158
  }
153
159
 
154
160
  function loadUserNormalizer(config, rules) {
155
161
  // Load the normalizer.
156
- var normalizer = new MetricNormalizer(config, 'user')
162
+ const normalizer = new MetricNormalizer(config, 'user')
157
163
  normalizer.loadFromConfig()
158
164
 
159
165
  if (rules && rules.length) {
@@ -167,7 +173,7 @@ function loadUserNormalizer(config, rules) {
167
173
  }
168
174
 
169
175
  function arrayContainsAny(array) {
170
- for (var i = 1; i < arguments.length; ++i) {
176
+ for (let i = 1; i < arguments.length; ++i) {
171
177
  if (array.indexOf(arguments[i]) !== -1) {
172
178
  return true
173
179
  }
package/bin/tracetractor CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  /*
4
3
  * Copyright 2020 New Relic Corporation. All rights reserved.
5
4
  * SPDX-License-Identifier: Apache-2.0
package/index.js CHANGED
@@ -16,7 +16,6 @@ const featureFlags = require('./lib/feature_flags').prerelease
16
16
  const psemver = require('./lib/util/process-version')
17
17
  let logger = require('./lib/logger') // Gets re-loaded after initialization.
18
18
 
19
-
20
19
  const pkgJSON = require('./package.json')
21
20
  logger.info(
22
21
  'Using New Relic for Node.js. Agent version: %s; Node version: %s.',
@@ -43,15 +42,13 @@ function initialize() {
43
42
  let message = null
44
43
 
45
44
  try {
46
- logger.debug(
47
- 'Process was running %s seconds before agent was loaded.',
48
- preAgentTime
49
- )
45
+ logger.debug('Process was running %s seconds before agent was loaded.', preAgentTime)
50
46
 
51
47
  if (!psemver.satisfies(pkgJSON.engines.node)) {
52
48
  // TODO: Update this message when Node v12 is deprecated.
53
- message = 'New Relic for Node.js requires a version of Node equal to or\n' +
54
- 'greater than 12.0.0. Not starting!'
49
+ message =
50
+ 'New Relic for Node.js requires a version of Node equal to or\n' +
51
+ 'greater than 12.0.0. Not starting!'
55
52
 
56
53
  logger.error(message)
57
54
  throw new Error(message)
@@ -61,7 +58,7 @@ function initialize() {
61
58
  if (psemver.satisfies('>=17.0.0')) {
62
59
  logger.warn(
63
60
  'New Relic for Node.js %s has not been tested on Node.js %s. Please ' +
64
- 'update the agent or downgrade your version of Node.js',
61
+ 'update the agent or downgrade your version of Node.js',
65
62
  pkgJSON.version,
66
63
  process.version
67
64
  )
@@ -132,9 +129,7 @@ function createAgent(config) {
132
129
  const appNames = agent.config.applications()
133
130
 
134
131
  if (config.logging.diagnostics) {
135
- logger.warn(
136
- 'Diagnostics logging is enabled, this may cause significant overhead.'
137
- )
132
+ logger.warn('Diagnostics logging is enabled, this may cause significant overhead.')
138
133
  }
139
134
 
140
135
  if (appNames.length < 1) {
@@ -176,9 +171,7 @@ function createAgent(config) {
176
171
  function addStartupSupportabilities(agent) {
177
172
  // TODO: As new versions come out, make sure to update Angler metrics.
178
173
  const nodeMajor = /^v?(\d+)/.exec(process.version)
179
- agent.recordSupportability(
180
- 'Nodejs/Version/' + ((nodeMajor && nodeMajor[1]) || 'unknown')
181
- )
174
+ agent.recordSupportability('Nodejs/Version/' + ((nodeMajor && nodeMajor[1]) || 'unknown'))
182
175
 
183
176
  const configFlags = Object.keys(agent.config.feature_flag)
184
177
  for (let i = 0; i < configFlags.length; ++i) {
package/lib/agent.js CHANGED
@@ -57,7 +57,9 @@ const DEFAULT_HARVEST_INTERVAL_MS = 60000
57
57
  function Agent(config) {
58
58
  EventEmitter.call(this)
59
59
 
60
- if (!config) throw new Error('Agent must be created with a configuration!')
60
+ if (!config) {
61
+ throw new Error('Agent must be created with a configuration!')
62
+ }
61
63
 
62
64
  // The agent base attributes which last throughout its lifetime.
63
65
  this._state = 'stopped'
@@ -84,10 +86,7 @@ function Agent(config) {
84
86
  this.collector
85
87
  )
86
88
 
87
- this.metrics.on(
88
- 'starting metric_data data send.',
89
- this._beforeMetricDataSend.bind(this)
90
- )
89
+ this.metrics.on('starting metric_data data send.', this._beforeMetricDataSend.bind(this))
91
90
 
92
91
  this.spanEventAggregator = createSpanEventAggregator(config, this.collector, this.metrics)
93
92
 
@@ -126,7 +125,7 @@ function Agent(config) {
126
125
  this.collector
127
126
  )
128
127
 
129
- const errorEventAggregator = new ErrorEventAggregator(
128
+ const errorEventAggregator = new ErrorEventAggregator(
130
129
  {
131
130
  periodMs: config.event_harvest_config.report_period_ms,
132
131
  limit: config.event_harvest_config.harvest_limits.error_event_data
@@ -135,12 +134,7 @@ function Agent(config) {
135
134
  this.metrics
136
135
  )
137
136
 
138
- this.errors = new ErrorCollector(
139
- config,
140
- errorTraceAggregator,
141
- errorEventAggregator,
142
- this.metrics
143
- )
137
+ this.errors = new ErrorCollector(config, errorTraceAggregator, errorEventAggregator, this.metrics)
144
138
 
145
139
  // Transaction tracing.
146
140
  this.tracer = new Tracer(this)
@@ -195,15 +189,16 @@ util.inherits(Agent, EventEmitter)
195
189
  * @param {Function} callback Continuation and error handler.
196
190
  */
197
191
  Agent.prototype.start = function start(callback) {
198
- if (!callback) throw new TypeError('callback required!')
192
+ if (!callback) {
193
+ throw new TypeError('callback required!')
194
+ }
199
195
 
200
196
  const agent = this
201
197
 
202
198
  this.setState('starting')
203
199
 
204
200
  if (this.config.agent_enabled !== true) {
205
- logger.warn('The New Relic Node.js agent is disabled by its configuration. ' +
206
- 'Not starting!')
201
+ logger.warn('The New Relic Node.js agent is disabled by its configuration. ' + 'Not starting!')
207
202
 
208
203
  this.setState('stopped')
209
204
  return process.nextTick(callback)
@@ -216,9 +211,11 @@ Agent.prototype.start = function start(callback) {
216
211
  }
217
212
 
218
213
  if (!this.config.license_key) {
219
- logger.error('A valid account license key cannot be found. ' +
220
- 'Has a license key been specified in the agent configuration ' +
221
- 'file or via the NEW_RELIC_LICENSE_KEY environment variable?')
214
+ logger.error(
215
+ 'A valid account license key cannot be found. ' +
216
+ 'Has a license key been specified in the agent configuration ' +
217
+ 'file or via the NEW_RELIC_LICENSE_KEY environment variable?'
218
+ )
222
219
 
223
220
  this.setState('errored')
224
221
  sampler.stop()
@@ -232,40 +229,17 @@ Agent.prototype.start = function start(callback) {
232
229
  if (error || response.shouldShutdownRun()) {
233
230
  agent.setState('errored')
234
231
  sampler.stop()
235
- callback(
236
- error || new Error('Failed to connect to collector'),
237
- response && response.payload
238
- )
232
+ callback(error || new Error('Failed to connect to collector'), response && response.payload)
239
233
  return
240
234
  }
241
235
 
242
236
  if (agent.collector.isConnected()) {
243
- agent.onConnect()
244
- agent.setState('started')
245
237
  const config = response.payload
246
238
 
247
- if (agent.config.no_immediate_harvest) {
248
- agent.startAggregators()
239
+ const shouldImmediatelyHarvest = !agent.config.no_immediate_harvest
240
+ agent.onConnect(shouldImmediatelyHarvest, () => {
249
241
  callback(null, config)
250
- } else {
251
- // For data collection that streams immediately, dont delay capture/sending until
252
- // the harvest of everything else has completed.
253
- agent.startStreaming()
254
-
255
- // Harvest immediately for quicker data display, but after at least 1
256
- // second or the collector will throw away the data.
257
- //
258
- // NOTE: this setTimeout is deliberately NOT unref'd due to it being
259
- // the last step in the Agent startup process
260
- setTimeout(function afterTimeout() {
261
- logger.info(`Starting initial ${INITIAL_HARVEST_DELAY_MS}ms harvest.`)
262
-
263
- agent.forceHarvestAll(function afterAllAggregatorsSend() {
264
- agent.startAggregators()
265
- callback(null, config)
266
- })
267
- }, INITIAL_HARVEST_DELAY_MS)
268
- }
242
+ })
269
243
  } else {
270
244
  callback(new Error('Collector did not connect and did not error'))
271
245
  }
@@ -281,12 +255,9 @@ Agent.prototype.forceHarvestAll = function forceHarvestAll(callback) {
281
255
  const promises = []
282
256
 
283
257
  const metricPromise = new Promise((resolve) => {
284
- agent.metrics.once(
285
- 'finished metric_data data send.',
286
- function onMetricsFinished() {
287
- resolve()
288
- }
289
- )
258
+ agent.metrics.once('finished metric_data data send.', function onMetricsFinished() {
259
+ resolve()
260
+ })
290
261
  agent.metrics.send()
291
262
  })
292
263
 
@@ -341,12 +312,9 @@ Agent.prototype.forceHarvestAll = function forceHarvestAll(callback) {
341
312
 
342
313
  if (agent.config.transaction_tracer.enabled && agent.config.collect_traces) {
343
314
  const transactionTracePromise = new Promise((resolve) => {
344
- agent.traces.once(
345
- 'finished transaction_sample_data data send.',
346
- function onTracesFinished() {
347
- resolve()
348
- }
349
- )
315
+ agent.traces.once('finished transaction_sample_data data send.', function onTracesFinished() {
316
+ resolve()
317
+ })
350
318
  agent.traces.send()
351
319
  })
352
320
 
@@ -355,20 +323,16 @@ Agent.prototype.forceHarvestAll = function forceHarvestAll(callback) {
355
323
 
356
324
  if (agent.config.slow_sql.enabled) {
357
325
  const sqlTracePromise = new Promise((resolve) => {
358
- agent.queries.once(
359
- 'finished sql_trace_data data send.',
360
- function onSqlTracesFinished() {
361
- resolve()
362
- }
363
- )
326
+ agent.queries.once('finished sql_trace_data data send.', function onSqlTracesFinished() {
327
+ resolve()
328
+ })
364
329
  agent.queries.send()
365
330
  })
366
331
 
367
332
  promises.push(sqlTracePromise)
368
333
  }
369
334
 
370
- const errorCollectorEnabled =
371
- agent.config.error_collector && agent.config.error_collector.enabled
335
+ const errorCollectorEnabled = agent.config.error_collector && agent.config.error_collector.enabled
372
336
 
373
337
  if (errorCollectorEnabled && agent.config.collect_errors) {
374
338
  const errorTracePromise = new Promise((resolve) => {
@@ -436,8 +400,7 @@ Agent.prototype.startAggregators = function startAggregators() {
436
400
  this.queries.start()
437
401
  }
438
402
 
439
- if (this.config.distributed_tracing.enabled &&
440
- this.config.span_events.enabled) {
403
+ if (this.config.distributed_tracing.enabled && this.config.span_events.enabled) {
441
404
  this.spanEventAggregator.start()
442
405
  }
443
406
 
@@ -450,18 +413,58 @@ Agent.prototype.startAggregators = function startAggregators() {
450
413
  }
451
414
  }
452
415
 
453
- Agent.prototype.onConnect = function onConnect() {
454
- this.metrics.reconfigure(this.config)
455
- this.errors.reconfigure(this.config)
456
- this.traces.reconfigure(this.config)
457
- this.queries.reconfigure(this.config)
458
- this.spanEventAggregator.reconfigure(this.config)
459
- this.transactionEventAggregator.reconfigure(this.config)
460
- this.customEventAggregator.reconfigure(this.config)
416
+ /**
417
+ * Completes any final setup upon full connection to New Relic
418
+ * servers and sets the agent state to 'started'.
419
+ */
420
+ Agent.prototype.onConnect = function onConnect(shouldImmediatelyHarvest, callback) {
421
+ this._reconfigureAggregators(this.config)
461
422
 
462
423
  if (this.config.certificates && this.config.certificates.length > 0) {
463
424
  this.metrics.getOrCreateMetric(NAMES.FEATURES.CERTIFICATES).incrementCallCount()
464
425
  }
426
+
427
+ this._scheduleHarvests(shouldImmediatelyHarvest, callback)
428
+
429
+ this.setState('started')
430
+ }
431
+
432
+ Agent.prototype._reconfigureAggregators = function _reconfigureAggregators(config) {
433
+ this.metrics.reconfigure(config)
434
+ this.errors.reconfigure(config)
435
+ this.traces.reconfigure(config)
436
+ this.queries.reconfigure(config)
437
+ this.spanEventAggregator.reconfigure(config)
438
+ this.transactionEventAggregator.reconfigure(config)
439
+ this.customEventAggregator.reconfigure(config)
440
+ }
441
+
442
+ Agent.prototype._scheduleHarvests = function _scheduleHarvests(shouldImmediatelyHarvest, callback) {
443
+ if (!shouldImmediatelyHarvest) {
444
+ this.startAggregators()
445
+ setImmediate(callback)
446
+ return
447
+ }
448
+
449
+ const agent = this
450
+
451
+ // For data collection that streams immediately, dont delay capture/sending until
452
+ // the harvest of everything else has completed.
453
+ agent.startStreaming()
454
+
455
+ // Harvest immediately for quicker data display, but after at least 1
456
+ // second or the collector will throw away the data.
457
+ //
458
+ // NOTE: this setTimeout is deliberately NOT unref'd due to it being
459
+ // the last step in the Agent startup process
460
+ setTimeout(function afterTimeout() {
461
+ logger.info(`Starting initial ${INITIAL_HARVEST_DELAY_MS}ms harvest.`)
462
+
463
+ agent.forceHarvestAll(function afterAllAggregatorsSend() {
464
+ agent.startAggregators()
465
+ callback()
466
+ })
467
+ }, INITIAL_HARVEST_DELAY_MS)
465
468
  }
466
469
 
467
470
  /**
@@ -471,9 +474,7 @@ Agent.prototype.onConnect = function onConnect() {
471
474
  * @param {Function} callback
472
475
  */
473
476
  Agent.prototype._serverlessModeStart = function _serverlessModeStart(callback) {
474
- logger.info(
475
- 'New Relic for Node.js starting in serverless mode -- skipping connection process.'
476
- )
477
+ logger.info('New Relic for Node.js starting in serverless mode -- skipping connection process.')
477
478
 
478
479
  setImmediate(() => callback(null, this.config))
479
480
  }
@@ -486,7 +487,9 @@ Agent.prototype._serverlessModeStart = function _serverlessModeStart(callback) {
486
487
  * current instrumentation and patch to the module loader.
487
488
  */
488
489
  Agent.prototype.stop = function stop(callback) {
489
- if (!callback) throw new TypeError('callback required!')
490
+ if (!callback) {
491
+ throw new TypeError('callback required!')
492
+ }
490
493
 
491
494
  const agent = this
492
495
 
@@ -597,12 +600,15 @@ Agent.prototype._beforeMetricDataSend = function _beforeMetricDataSend() {
597
600
  Agent.prototype._generateEntityStatsAndClear = function _generateHarvestMetrics() {
598
601
  // Note some information about the size of this harvest.
599
602
  if (logger.traceEnabled()) {
600
- logger.trace({
601
- segmentTotal: this.totalActiveSegments,
602
- harvestCreated: this.segmentsCreatedInHarvest,
603
- harvestCleared: this.segmentsClearedInHarvest,
604
- activeTransactions: this.activeTransactions
605
- }, 'Entity stats on metric harvest')
603
+ logger.trace(
604
+ {
605
+ segmentTotal: this.totalActiveSegments,
606
+ harvestCreated: this.segmentsCreatedInHarvest,
607
+ harvestCleared: this.segmentsClearedInHarvest,
608
+ activeTransactions: this.activeTransactions
609
+ },
610
+ 'Entity stats on metric harvest'
611
+ )
606
612
  }
607
613
 
608
614
  // Reset the counters.
@@ -618,7 +624,9 @@ Agent.prototype._generateEntityStatsAndClear = function _generateHarvestMetrics(
618
624
  * @param {object} configuration New config JSON from the collector.
619
625
  */
620
626
  Agent.prototype.reconfigure = function reconfigure(configuration) {
621
- if (!configuration) throw new TypeError('must pass configuration')
627
+ if (!configuration) {
628
+ throw new TypeError('must pass configuration')
629
+ }
622
630
 
623
631
  this.config.onConnect(configuration)
624
632
  }
@@ -709,10 +717,8 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
709
717
  }
710
718
  } else if (
711
719
  this.config.cross_application_tracer.enabled &&
712
- !transaction.invalidIncomingExternalTransaction && (
713
- transaction.referringTransactionGuid ||
714
- transaction.includesOutboundRequests()
715
- )
720
+ !transaction.invalidIncomingExternalTransaction &&
721
+ (transaction.referringTransactionGuid || transaction.includesOutboundRequests())
716
722
  ) {
717
723
  intrinsicAttributes['nr.guid'] = transaction.id
718
724
  intrinsicAttributes['nr.tripId'] = transaction.tripId || transaction.id
@@ -725,19 +731,17 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
725
731
  intrinsicAttributes['nr.referringPathHash'] = transaction.referringPathHash
726
732
  }
727
733
  if (transaction.referringTransactionGuid) {
728
- var refId = transaction.referringTransactionGuid
734
+ const refId = transaction.referringTransactionGuid
729
735
  intrinsicAttributes['nr.referringTransactionGuid'] = refId
730
736
  }
731
- var alternatePathHashes = transaction.alternatePathHashes()
737
+ const alternatePathHashes = transaction.alternatePathHashes()
732
738
  if (alternatePathHashes) {
733
739
  intrinsicAttributes['nr.alternatePathHashes'] = alternatePathHashes
734
740
  }
735
741
  if (transaction.baseSegment && transaction.type === 'web') {
736
- var apdex = (
737
- this.config.web_transactions_apdex[transaction.getFullName()] ||
738
- this.config.apdex_t
739
- )
740
- var duration = transaction.baseSegment.getDurationInMillis() / 1000
742
+ const apdex =
743
+ this.config.web_transactions_apdex[transaction.getFullName()] || this.config.apdex_t
744
+ const duration = transaction.baseSegment.getDurationInMillis() / 1000
741
745
  intrinsicAttributes['nr.apdexPerfZone'] = calculateApdexZone(duration, apdex)
742
746
  }
743
747
  }
@@ -764,17 +768,15 @@ function calculateApdexZone(duration, apdexT) {
764
768
  }
765
769
 
766
770
  Agent.prototype._addEventFromTransaction = function _addEventFromTransaction(tx) {
767
- if (!this.config.transaction_events.enabled) return
771
+ if (!this.config.transaction_events.enabled) {
772
+ return
773
+ }
768
774
 
769
775
  const intrinsicAttributes = this._addIntrinsicAttrsFromTransaction(tx)
770
776
  const userAttributes = tx.trace.custom.get(DESTINATIONS.TRANS_EVENT)
771
777
  const agentAttributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT)
772
778
 
773
- const event = [
774
- intrinsicAttributes,
775
- userAttributes,
776
- agentAttributes
777
- ]
779
+ const event = [intrinsicAttributes, userAttributes, agentAttributes]
778
780
 
779
781
  this.transactionEventAggregator.add(event, tx.priority || Math.random())
780
782
  }
@@ -822,9 +824,9 @@ Agent.prototype.setLambdaArn = function setLambdaArn(arn) {
822
824
  }
823
825
  }
824
826
 
825
- Agent.prototype.setLambdaFunctionVersion = function setLambdaFunctionVersion(function_version) {
827
+ Agent.prototype.setLambdaFunctionVersion = function setLambdaFunctionVersion(functionVersion) {
826
828
  if (this.collector instanceof ServerlessCollector) {
827
- this.collector.setLambdaFunctionVersion(function_version)
829
+ this.collector.setLambdaFunctionVersion(functionVersion)
828
830
  }
829
831
  }
830
832
 
@@ -865,12 +867,9 @@ Agent.prototype._listenForConfigChanges = function _listenForConfigChanges() {
865
867
  this.config.on('sampling_target', function updateSamplingTarget(target) {
866
868
  self.transactionSampler.samplingTarget = target
867
869
  })
868
- this.config.on(
869
- 'sampling_target_period_in_seconds',
870
- function updateSamplePeriod(period) {
871
- self.transactionSampler.samplingPeriod = period * 1000
872
- }
873
- )
870
+ this.config.on('sampling_target_period_in_seconds', function updateSamplePeriod(period) {
871
+ self.transactionSampler.samplingPeriod = period * 1000
872
+ })
874
873
  this.config.on('event_harvest_config', function onHarvestConfigReceived(harvestConfig) {
875
874
  if (harvestConfig) {
876
875
  generateEventHarvestSupportMetrics(self, harvestConfig)
@@ -889,9 +888,7 @@ function generateEventHarvestSupportMetrics(agent, harvestConfig) {
889
888
 
890
889
  const analyticLimit = harvestLimits.analytic_event_data
891
890
  if (analyticLimit) {
892
- const analyticLimitMetric = agent.metrics.getOrCreateMetric(
893
- harvestLimitNames.ANALYTIC
894
- )
891
+ const analyticLimitMetric = agent.metrics.getOrCreateMetric(harvestLimitNames.ANALYTIC)
895
892
  analyticLimitMetric.recordValue(analyticLimit)
896
893
  }
897
894
 
@@ -6,7 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  const EventEmitter = require('events').EventEmitter
9
- const logger = require('../logger').child({component: 'base_aggregator'})
9
+ const logger = require('../logger').child({ component: 'base_aggregator' })
10
10
 
11
11
  class Aggregator extends EventEmitter {
12
12
  constructor(opts, collector) {