newrelic 7.5.2 → 8.3.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 (158) hide show
  1. package/NEWS.md +4989 -4886
  2. package/THIRD_PARTY_NOTICES.md +625 -216
  3. package/api.js +105 -174
  4. package/bin/test-naming-rules.js +38 -32
  5. package/bin/tracetractor +0 -1
  6. package/index.js +12 -18
  7. package/lib/agent.js +108 -111
  8. package/lib/aggregators/base-aggregator.js +1 -1
  9. package/lib/aggregators/event-aggregator.js +6 -6
  10. package/lib/attributes.js +12 -13
  11. package/lib/collector/api.js +32 -42
  12. package/lib/collector/facts.js +67 -65
  13. package/lib/collector/http-agents.js +30 -27
  14. package/lib/collector/parse-response.js +1 -2
  15. package/lib/collector/remote-method.js +43 -36
  16. package/lib/collector/serverless.js +13 -18
  17. package/lib/collector/ssl/certificates.js +1056 -1056
  18. package/lib/config/attribute-filter.js +90 -82
  19. package/lib/config/default.js +30 -18
  20. package/lib/config/env.js +17 -12
  21. package/lib/config/harvest-config-validator.js +1 -1
  22. package/lib/config/index.js +160 -177
  23. package/lib/config/merge-server-config.js +7 -5
  24. package/lib/custom-events/custom-event-aggregator.js +1 -1
  25. package/lib/db/parse-sql.js +6 -9
  26. package/lib/db/parsed-statement.js +6 -13
  27. package/lib/db/query-parsers/sql.js +6 -9
  28. package/lib/db/query-sample.js +7 -3
  29. package/lib/db/query-trace-aggregator.js +12 -12
  30. package/lib/db/utils.js +1 -1
  31. package/lib/environment.js +173 -138
  32. package/lib/errors/error-collector.js +18 -31
  33. package/lib/errors/error-event-aggregator.js +1 -1
  34. package/lib/errors/error-trace-aggregator.js +2 -3
  35. package/lib/errors/helper.js +21 -30
  36. package/lib/errors/index.js +16 -28
  37. package/lib/feature_flags.js +5 -8
  38. package/lib/grpc/connection/states.js +6 -6
  39. package/lib/grpc/connection.js +35 -46
  40. package/lib/header-attributes.js +49 -53
  41. package/lib/instrumentation/amqplib.js +8 -17
  42. package/lib/instrumentation/bluebird.js +61 -20
  43. package/lib/instrumentation/cassandra-driver.js +2 -2
  44. package/lib/instrumentation/connect.js +4 -3
  45. package/lib/instrumentation/core/async_hooks.js +11 -4
  46. package/lib/instrumentation/core/child_process.js +20 -28
  47. package/lib/instrumentation/core/crypto.js +1 -7
  48. package/lib/instrumentation/core/dns.js +3 -7
  49. package/lib/instrumentation/core/domain.js +2 -8
  50. package/lib/instrumentation/core/fs.js +22 -37
  51. package/lib/instrumentation/core/globals.js +3 -7
  52. package/lib/instrumentation/core/http-outbound.js +15 -40
  53. package/lib/instrumentation/core/http.js +29 -63
  54. package/lib/instrumentation/core/inspector.js +6 -10
  55. package/lib/instrumentation/core/net.js +3 -1
  56. package/lib/instrumentation/core/timers.js +17 -24
  57. package/lib/instrumentation/core/zlib.js +2 -10
  58. package/lib/instrumentation/express.js +4 -2
  59. package/lib/instrumentation/fastify/spec-builders.js +5 -0
  60. package/lib/instrumentation/fastify.js +37 -10
  61. package/lib/instrumentation/hapi/hapi-17.js +9 -10
  62. package/lib/instrumentation/hapi.js +15 -15
  63. package/lib/instrumentation/ioredis.js +1 -2
  64. package/lib/instrumentation/memcached.js +39 -43
  65. package/lib/instrumentation/mongodb/common.js +218 -0
  66. package/lib/instrumentation/mongodb/constants.js +87 -0
  67. package/lib/instrumentation/mongodb/v2-mongo.js +110 -0
  68. package/lib/instrumentation/mongodb/v3-mongo.js +80 -0
  69. package/lib/instrumentation/mongodb/v4-mongo.js +90 -0
  70. package/lib/instrumentation/mongodb.js +20 -312
  71. package/lib/instrumentation/mysql.js +33 -26
  72. package/lib/instrumentation/oracle.js +10 -14
  73. package/lib/instrumentation/pg.js +30 -21
  74. package/lib/instrumentation/promise.js +20 -17
  75. package/lib/instrumentation/redis.js +30 -30
  76. package/lib/instrumentation/when.js +9 -1
  77. package/lib/instrumentations.js +24 -24
  78. package/lib/logger.js +1 -1
  79. package/lib/metrics/index.js +37 -17
  80. package/lib/metrics/mapper.js +9 -9
  81. package/lib/metrics/metric-aggregator.js +5 -10
  82. package/lib/metrics/names.js +8 -7
  83. package/lib/metrics/normalizer/rule.js +6 -7
  84. package/lib/metrics/normalizer/tx_segment.js +17 -13
  85. package/lib/metrics/normalizer.js +30 -33
  86. package/lib/metrics/recorders/custom.js +3 -1
  87. package/lib/metrics/recorders/distributed-trace.js +3 -18
  88. package/lib/metrics/recorders/generic.js +3 -2
  89. package/lib/metrics/recorders/http.js +4 -6
  90. package/lib/metrics/recorders/http_external.js +1 -3
  91. package/lib/metrics/recorders/message-transaction.js +2 -12
  92. package/lib/metrics/recorders/other.js +2 -12
  93. package/lib/parse-proc-cpuinfo.js +11 -16
  94. package/lib/parse-proc-meminfo.js +5 -3
  95. package/lib/prioritized-attributes.js +12 -17
  96. package/lib/priority-queue.js +1 -1
  97. package/lib/proxy/grpc.js +1 -1
  98. package/lib/reservoir.js +9 -3
  99. package/lib/sampler.js +12 -13
  100. package/lib/serverless/api-gateway.js +3 -3
  101. package/lib/serverless/aws-lambda.js +28 -37
  102. package/lib/shim/conglomerate-shim.js +4 -4
  103. package/lib/shim/datastore-shim.js +29 -38
  104. package/lib/shim/index.js +8 -9
  105. package/lib/shim/message-shim.js +111 -113
  106. package/lib/shim/promise-shim.js +18 -13
  107. package/lib/shim/shim.js +72 -66
  108. package/lib/shim/specs/index.js +18 -19
  109. package/lib/shim/transaction-shim.js +26 -36
  110. package/lib/shim/webframework-shim.js +25 -35
  111. package/lib/shimmer.js +184 -166
  112. package/lib/spans/create-span-event-aggregator.js +24 -44
  113. package/lib/spans/span-context.js +4 -10
  114. package/lib/spans/span-event-aggregator.js +68 -13
  115. package/lib/spans/span-event.js +5 -7
  116. package/lib/spans/span-streamer.js +10 -18
  117. package/lib/spans/streaming-span-event-aggregator.js +1 -1
  118. package/lib/spans/streaming-span-event.js +4 -4
  119. package/lib/stats/apdex.js +5 -11
  120. package/lib/stats/index.js +12 -17
  121. package/lib/system-info.js +7 -3
  122. package/lib/timer.js +30 -16
  123. package/lib/transaction/dt-payload.js +1 -1
  124. package/lib/transaction/handle.js +19 -19
  125. package/lib/transaction/index.js +94 -112
  126. package/lib/transaction/name-state.js +5 -6
  127. package/lib/transaction/trace/aggregator.js +78 -73
  128. package/lib/transaction/trace/exclusive-time-calculator.js +5 -9
  129. package/lib/transaction/trace/index.js +26 -24
  130. package/lib/transaction/trace/segment.js +39 -56
  131. package/lib/transaction/tracecontext.js +37 -45
  132. package/lib/transaction/tracer/index.js +79 -44
  133. package/lib/transaction/transaction-event-aggregator.js +29 -31
  134. package/lib/uninstrumented.js +4 -5
  135. package/lib/util/attribute-types.js +1 -5
  136. package/lib/util/byte-limit.js +0 -1
  137. package/lib/util/cat.js +5 -13
  138. package/lib/util/codec.js +8 -4
  139. package/lib/util/deep-equal.js +48 -18
  140. package/lib/util/flatten.js +5 -2
  141. package/lib/util/hashes.js +2 -2
  142. package/lib/util/label-parser.js +7 -13
  143. package/lib/util/logger.js +31 -13
  144. package/lib/util/process-version.js +1 -1
  145. package/lib/util/properties.js +1 -1
  146. package/lib/util/sql/obfuscate.js +7 -17
  147. package/lib/util/stream-sink.js +2 -3
  148. package/lib/util/urltils.js +9 -13
  149. package/lib/utilization/aws-info.js +2 -3
  150. package/lib/utilization/azure-info.js +32 -30
  151. package/lib/utilization/common.js +5 -4
  152. package/lib/utilization/docker-info.js +4 -6
  153. package/lib/utilization/gcp-info.js +36 -35
  154. package/lib/utilization/index.js +1 -1
  155. package/lib/utilization/kubernetes-info.js +2 -2
  156. package/lib/utilization/pcf-info.js +4 -4
  157. package/package.json +32 -18
  158. package/stub_api.js +8 -6
@@ -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
@@ -19,7 +18,7 @@ var 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]),
@@ -73,8 +72,8 @@ function run(opts) {
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
+ var urlsFile = fs.createReadStream(opts.urls, { encoding: 'utf-8' })
76
+ var reader = readline.createInterface({ input: urlsFile, output: null })
78
77
  reader.on('line', function onUrlLine(urlLine) {
79
78
  appliedRules = []
80
79
  var scrubbedUrl = urltils.scrub(urlLine)
@@ -93,7 +92,10 @@ function run(opts) {
93
92
  var 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
  }
@@ -120,33 +122,37 @@ function loadDefaultNormalizer(config) {
120
122
  var 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
  }
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,24 +42,23 @@ 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
- // TODO: Update this check when Node v10 is deprecated.
52
- if (psemver.satisfies('<10.0.0')) {
53
- message = 'New Relic for Node.js requires a version of Node equal to or\n' +
54
- 'greater than 10.0.0. Not starting!'
47
+ if (!psemver.satisfies(pkgJSON.engines.node)) {
48
+ // TODO: Update this message when Node v12 is deprecated.
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)
55
+ }
58
56
 
59
- // TODO: Update this check when Node v16 support is added
60
- } else if (!psemver.satisfies(pkgJSON.engines.node) || psemver.satisfies('>=15.0.0')) {
57
+ // TODO: Update this check when Node v18 support is added
58
+ if (psemver.satisfies('>=17.0.0')) {
61
59
  logger.warn(
62
60
  'New Relic for Node.js %s has not been tested on Node.js %s. Please ' +
63
- 'update the agent or downgrade your version of Node.js',
61
+ 'update the agent or downgrade your version of Node.js',
64
62
  pkgJSON.version,
65
63
  process.version
66
64
  )
@@ -131,9 +129,7 @@ function createAgent(config) {
131
129
  const appNames = agent.config.applications()
132
130
 
133
131
  if (config.logging.diagnostics) {
134
- logger.warn(
135
- 'Diagnostics logging is enabled, this may cause significant overhead.'
136
- )
132
+ logger.warn('Diagnostics logging is enabled, this may cause significant overhead.')
137
133
  }
138
134
 
139
135
  if (appNames.length < 1) {
@@ -175,9 +171,7 @@ function createAgent(config) {
175
171
  function addStartupSupportabilities(agent) {
176
172
  // TODO: As new versions come out, make sure to update Angler metrics.
177
173
  const nodeMajor = /^v?(\d+)/.exec(process.version)
178
- agent.recordSupportability(
179
- 'Nodejs/Version/' + ((nodeMajor && nodeMajor[1]) || 'unknown')
180
- )
174
+ agent.recordSupportability('Nodejs/Version/' + ((nodeMajor && nodeMajor[1]) || 'unknown'))
181
175
 
182
176
  const configFlags = Object.keys(agent.config.feature_flag)
183
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
@@ -733,10 +739,8 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
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
- )
742
+ var apdex =
743
+ this.config.web_transactions_apdex[transaction.getFullName()] || this.config.apdex_t
740
744
  var duration = transaction.baseSegment.getDurationInMillis() / 1000
741
745
  intrinsicAttributes['nr.apdexPerfZone'] = calculateApdexZone(duration, apdex)
742
746
  }
@@ -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) {
@@ -6,7 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  const Aggregator = require('./base-aggregator')
9
- const logger = require('../logger').child({component: 'event_aggregator'})
9
+ const logger = require('../logger').child({ component: 'event_aggregator' })
10
10
  const PriorityQueue = require('../priority-queue')
11
11
 
12
12
  /**
@@ -49,7 +49,7 @@ class EventAggregator extends Aggregator {
49
49
 
50
50
  const didAdd = this.addEvent.apply(this, arguments)
51
51
 
52
- if (didAdd && (this._items.overflow() === 0)) {
52
+ if (didAdd && this._items.overflow() === 0) {
53
53
  this._metrics.getOrCreateMetric(this._metricNames.SENT).incrementCallCount()
54
54
  } else {
55
55
  this._metrics.getOrCreateMetric(this._metricNames.DROPPED).incrementCallCount()
@@ -129,7 +129,9 @@ class EventAggregator extends Aggregator {
129
129
  const toMerge = Math.min(events.length, this.limit - this.length)
130
130
  logger.warn(
131
131
  'Merging %d of %d events into %s for next harvest',
132
- toMerge, events.length, this.constructor.name
132
+ toMerge,
133
+ events.length,
134
+ this.constructor.name
133
135
  )
134
136
 
135
137
  const seen = events.length
@@ -140,9 +142,7 @@ class EventAggregator extends Aggregator {
140
142
  this._metrics.getOrCreateMetric(this._metricNames.SENT).incrementCallCount(sent)
141
143
 
142
144
  if (dropped > 0) {
143
- this._metrics
144
- .getOrCreateMetric(this._metricNames.DROPPED)
145
- .incrementCallCount(dropped)
145
+ this._metrics.getOrCreateMetric(this._metricNames.DROPPED).incrementCallCount(dropped)
146
146
  }
147
147
 
148
148
  // merge modifies incoming events collection.