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
@@ -5,8 +5,7 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- /* eslint sonarjs/cognitive-complexity: ["error", 16] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
-
8
+ const http = require('http')
10
9
  const CollectorResponse = require('./response')
11
10
  const facts = require('./facts')
12
11
  const logger = require('../logger').child({ component: 'collector_api' })
@@ -38,8 +37,8 @@ const FAILURE_DISCARD_DATA = new Set([400, 403, 404, 405, 407, 411, 413, 414, 41
38
37
  const AGENT_RUN_BEHAVIOR = CollectorResponse.AGENT_RUN_BEHAVIOR
39
38
 
40
39
  /**
41
- * @param errors
42
- * @param name
40
+ * @param {Array} errors list of errors
41
+ * @param {string} name collector endpoint name
43
42
  */
44
43
  function dumpErrors(errors, name) {
45
44
  let index = 1
@@ -56,7 +55,7 @@ function dumpErrors(errors, name) {
56
55
  }
57
56
 
58
57
  /**
59
- * @param agent
58
+ * @param {Agent} agent New Relic agent
60
59
  */
61
60
  function CollectorAPI(agent) {
62
61
  this._agent = agent
@@ -99,7 +98,7 @@ CollectorAPI.prototype._throwCallbackError = function _throwCallbackError() {
99
98
  * Updates all methods except preconnect w/ new host/port pairs sent down from server
100
99
  * during preconnect (via redirect_host). Preconnect does not update.
101
100
  *
102
- * @param endpoint
101
+ * @param {string} endpoint collector name
103
102
  */
104
103
  CollectorAPI.prototype._updateEndpoints = function _updateEndpoints(endpoint) {
105
104
  logger.trace('Updating endpoints to: ', endpoint)
@@ -120,105 +119,109 @@ CollectorAPI.prototype.connect = function connect(callback) {
120
119
 
121
120
  this._agent.setState('connecting')
122
121
 
123
- const api = this
124
- const max = BACKOFFS.length
125
- const errors = []
126
- let attempts = 1
127
-
128
- const metric = this._agent.metrics.getOrCreateMetric(
129
- NAMES.SUPPORTABILITY.REGISTRATION + '/Attempts'
130
- )
131
-
132
122
  // Reset headers map for good measure
133
123
  if (this._reqHeadersMap) {
134
124
  this._reqHeadersMap = null
135
125
  }
136
126
 
137
- /**
138
- * Checks if proxy is configured to connect via `proxy_host` and `proxy_port`
139
- * and if error code is EPROTO or ECONNRESET. This is an indication their proxy
140
- * server only accepts HTTP connections, and we should provide an actionable warning to
141
- * fix the misconfiguration by setting `proxy` to a fully qualified URL
142
- *
143
- * @param {Error} error
144
- * @returns {boolean}
145
- */
146
- function isProxyMisconfigured(error) {
147
- const config = api._agent.config
148
- return (
149
- error &&
150
- ['EPROTO', 'ECONNRESET'].includes(error.code) &&
151
- config.proxy_host &&
152
- config.proxy_port &&
153
- !config.proxy
154
- )
127
+ const ctx = {
128
+ callback,
129
+ max: BACKOFFS.length,
130
+ errors: [],
131
+ attempts: 1
155
132
  }
133
+ this._login(this._retry.bind(this, ctx))
134
+ }
156
135
 
157
- /**
158
- * @param error
159
- * @param response
160
- */
161
- function retry(error, response) {
162
- metric.incrementCallCount()
136
+ /**
137
+ * Checks if proxy is configured to connect via `proxy_host` and `proxy_port`
138
+ * and if error code is EPROTO or ECONNRESET. This is an indication their proxy
139
+ * server only accepts HTTP connections, and we should provide an actionable warning to
140
+ * fix the misconfiguration by setting `proxy` to a fully qualified URL
141
+ *
142
+ * @param {Error} error response error
143
+ * @returns {boolean} determines if proxy is properly configured
144
+ */
145
+ CollectorAPI.prototype._isProxyMisconfigured = function _isProxyMisconfigured(error) {
146
+ const config = this._agent.config
147
+ return (
148
+ error &&
149
+ ['EPROTO', 'ECONNRESET'].includes(error.code) &&
150
+ config.proxy_host &&
151
+ config.proxy_port &&
152
+ !config.proxy
153
+ )
154
+ }
163
155
 
164
- if (error) {
165
- errors.push(error)
166
- } else if (response && SUCCESS.has(response.status)) {
167
- dumpErrors(errors, 'connect')
168
- return callback(null, CollectorResponse.success(response.payload))
169
- }
170
- if (!response) {
171
- response = CollectorResponse.retry()
172
- }
156
+ /**
157
+ * @param {object} ctx context object to pass from parent and between recursions.
158
+ * @param {Error} error response error
159
+ * @param {http.ServerResponse} response response from collector
160
+ * @returns {void}
161
+ */
162
+ CollectorAPI.prototype._retry = function _retry(ctx, error, response) {
163
+ const api = this
164
+ const metric = this._agent.metrics.getOrCreateMetric(
165
+ NAMES.SUPPORTABILITY.REGISTRATION + '/Attempts'
166
+ )
173
167
 
174
- // Retry everything except for an explicit Disconnect response code.
175
- if (response.status === 410 || response.agentRun === AGENT_RUN_BEHAVIOR.SHUTDOWN) {
176
- logger.error('The New Relic collector rejected this agent.')
177
- return callback(null, CollectorResponse.fatal(response.payload))
178
- } else if (response.status === 401) {
179
- logger.warn(
180
- error,
181
- 'Your license key appears to be invalid. Reattempting connection to New' +
182
- ' Relic. If the problem persists, please contact support@newrelic.com.' +
183
- ' (status code %s)',
184
- response.status
185
- )
186
- } else if (isProxyMisconfigured(error)) {
187
- logger.warn(
188
- error,
189
- 'Your proxy server appears to be configured to accept connections over http. ' +
190
- 'When setting `proxy_host` and `proxy_port` New Relic attempts to connect over ' +
191
- 'SSL(https). If your proxy is configured to accept connections over http, try ' +
192
- 'setting `proxy` to a fully qualified URL(e.g http://proxy-host:8080).'
193
- )
194
- }
168
+ metric.incrementCallCount()
195
169
 
196
- const backoff = BACKOFFS[Math.min(attempts, max) - 1]
197
- if (backoff.warn) {
198
- logger.warn('No connection has been established to New Relic after %d attempts.', attempts)
199
- }
170
+ if (error) {
171
+ ctx.errors.push(error)
172
+ } else if (response && SUCCESS.has(response.status)) {
173
+ dumpErrors(ctx.errors, 'connect')
174
+ ctx.callback(null, CollectorResponse.success(response.payload))
175
+ return
176
+ }
177
+ if (!response) {
178
+ response = CollectorResponse.retry()
179
+ }
200
180
 
201
- logger.debug(
181
+ // Retry everything except for an explicit Disconnect response code.
182
+ if (response.status === 410 || response.agentRun === AGENT_RUN_BEHAVIOR.SHUTDOWN) {
183
+ logger.error('The New Relic collector rejected this agent.')
184
+ return ctx.callback(null, CollectorResponse.fatal(response.payload))
185
+ } else if (response.status === 401) {
186
+ logger.warn(
187
+ error,
188
+ 'Your license key appears to be invalid. Reattempting connection to New' +
189
+ ' Relic. If the problem persists, please contact support@newrelic.com.' +
190
+ ' (status code %s)',
191
+ response.status
192
+ )
193
+ } else if (this._isProxyMisconfigured(error)) {
194
+ logger.warn(
202
195
  error,
203
- 'Failed to connect to New Relic after attempt %d, waiting %ds to retry.',
204
- attempts,
205
- backoff.interval
196
+ 'Your proxy server appears to be configured to accept connections over http. ' +
197
+ 'When setting `proxy_host` and `proxy_port` New Relic attempts to connect over ' +
198
+ 'SSL(https). If your proxy is configured to accept connections over http, try ' +
199
+ 'setting `proxy` to a fully qualified URL(e.g http://proxy-host:8080).'
206
200
  )
201
+ }
207
202
 
208
- ++attempts
209
- const timeout = setTimeout(function again() {
210
- api._login(retry)
211
- }, backoff.interval * TO_MILLIS)
212
- timeout.unref()
203
+ const backoff = BACKOFFS[Math.min(ctx.attempts, ctx.max) - 1]
204
+ if (backoff.warn) {
205
+ logger.warn('No connection has been established to New Relic after %d attempts.', ctx.attempts)
213
206
  }
214
207
 
215
- this._login(retry)
208
+ logger.debug(
209
+ error,
210
+ 'Failed to connect to New Relic after attempt %d, waiting %ds to retry.',
211
+ ctx.attempts,
212
+ backoff.interval
213
+ )
214
+
215
+ ++ctx.attempts
216
+ const timeout = setTimeout(function again() {
217
+ api._login(api._retry.bind(api, ctx))
218
+ }, backoff.interval * TO_MILLIS)
219
+ timeout.unref()
216
220
  }
217
221
 
218
222
  CollectorAPI.prototype._login = function _login(callback) {
219
223
  const methods = this._methods
220
224
  const agent = this._agent
221
- const self = this
222
225
 
223
226
  const preconnectData = { high_security: agent.config.high_security }
224
227
  if (agent.config.security_policies_token) {
@@ -227,56 +230,73 @@ CollectorAPI.prototype._login = function _login(callback) {
227
230
 
228
231
  const payload = [preconnectData]
229
232
 
230
- methods.preconnect.invoke(payload, onPreConnect)
233
+ methods.preconnect.invoke(payload, this._onPreConnect.bind(this, callback))
234
+ }
231
235
 
232
- /**
233
- * @param error
234
- * @param response
235
- */
236
- function onPreConnect(error, response) {
237
- if (error || !SUCCESS.has(response.status)) {
238
- return callback(error, response)
239
- }
236
+ /**
237
+ * @param {Function} callback function to run after processing response
238
+ * @param {Error} error response error
239
+ * @param {http.ServerResponse} response collector response from pre connect
240
+ * @returns {void}
241
+ */
242
+ CollectorAPI.prototype._onPreConnect = function _onPreConnect(callback, error, response) {
243
+ const agent = this._agent
244
+ if (error || !SUCCESS.has(response.status)) {
245
+ callback(error, response)
246
+ return
247
+ }
240
248
 
241
- const res = response.payload || Object.create(null)
242
- if (!res.redirect_host) {
249
+ const res = response.payload || Object.create(null)
250
+ this._handlePreConnectResponse(res)
251
+
252
+ const policies = res.security_policies || Object.create(null)
253
+
254
+ const laspResponse = agent.config.applyLasp(agent, policies)
255
+ if (laspResponse.shouldShutdownRun()) {
256
+ callback(null, laspResponse)
257
+ return
258
+ }
259
+
260
+ this._getFacts(laspResponse.payload, callback)
261
+ }
262
+
263
+ /**
264
+ * Checks the redirect_host and determines based on the URL if the collector
265
+ * needs to update the endpoint with new endpoint
266
+ *
267
+ * @param {http.ServerResponse} res collector response
268
+ */
269
+ CollectorAPI.prototype._handlePreConnectResponse = function _handlePreConnectResponse(res) {
270
+ const agent = this._agent
271
+
272
+ if (!res.redirect_host) {
273
+ logger.error(
274
+ "Requesting this account's collector from %s failed; trying default.",
275
+ agent.config.host
276
+ )
277
+ } else {
278
+ const parts = res.redirect_host.split(':')
279
+ if (parts.length > 2) {
243
280
  logger.error(
244
- "Requesting this account's collector from %s failed; trying default.",
245
- agent.config.host
281
+ "Requesting collector from %s returned bogus result '%s'; trying default.",
282
+ agent.config.host,
283
+ res.redirect_host
246
284
  )
247
285
  } else {
248
- const parts = res.redirect_host.split(':')
249
- if (parts.length > 2) {
250
- logger.error(
251
- "Requesting collector from %s returned bogus result '%s'; trying default.",
252
- agent.config.host,
253
- res.redirect_host
254
- )
255
- } else {
256
- logger.debug(
257
- "Requesting this account's collector from %s returned %s; reconfiguring.",
258
- agent.config.host,
259
- res.redirect_host
260
- )
261
-
262
- const [host, port] = parts
263
- const newEndpoint = {
264
- host: host,
265
- port: port || DEFAULT_PORT
266
- }
286
+ logger.debug(
287
+ "Requesting this account's collector from %s returned %s; reconfiguring.",
288
+ agent.config.host,
289
+ res.redirect_host
290
+ )
267
291
 
268
- self._updateEndpoints(newEndpoint)
292
+ const [host, port] = parts
293
+ const newEndpoint = {
294
+ host: host,
295
+ port: port || DEFAULT_PORT
269
296
  }
270
- }
271
297
 
272
- const policies = res.security_policies || Object.create(null)
273
-
274
- const laspResponse = agent.config.applyLasp(agent, policies)
275
- if (laspResponse.shouldShutdownRun()) {
276
- return callback(null, laspResponse)
298
+ this._updateEndpoints(newEndpoint)
277
299
  }
278
-
279
- self._getFacts(laspResponse.payload, callback)
280
300
  }
281
301
  }
282
302
 
@@ -298,50 +318,56 @@ CollectorAPI.prototype._getFacts = function _getFacts(lasp, callback) {
298
318
  }
299
319
 
300
320
  CollectorAPI.prototype._connect = function _connect(env, callback) {
301
- const collector = this
302
321
  const methods = this._methods
303
- const agent = this._agent
322
+ methods.connect.invoke(env, this._onConnect.bind(this, callback))
323
+ }
304
324
 
305
- methods.connect.invoke(env, onConnect)
325
+ /**
326
+ *
327
+ * Handles the response to the connect call
328
+ *
329
+ * @param {Function} callback function to run after processing response
330
+ * @param {Error} error collector response error
331
+ * @param {http.ServerOptions} res collector response
332
+ */
333
+ CollectorAPI.prototype._onConnect = function _onConnect(callback, error, res) {
334
+ const agent = this._agent
335
+ const methods = this._methods
306
336
 
307
- /**
308
- * @param error
309
- * @param res
310
- */
311
- function onConnect(error, res) {
312
- if (error || !SUCCESS.has(res.status)) {
313
- return callback(error, res)
314
- }
337
+ if (error || !SUCCESS.has(res.status)) {
338
+ callback(error, res)
339
+ return
340
+ }
315
341
 
316
- const config = res.payload
317
- if (!config || !config.agent_run_id) {
318
- return callback(new Error('No agent run ID received from handshake.'), res)
319
- }
342
+ const config = res.payload
343
+ if (!config || !config.agent_run_id) {
344
+ callback(new Error('No agent run ID received from handshake.'), res)
345
+ return
346
+ }
320
347
 
321
- agent.setState('connected')
348
+ agent.setState('connected')
322
349
 
323
- logger.info(
324
- 'Connected to %s:%d with agent run ID %s.',
325
- methods.connect.endpoint.host,
326
- methods.connect.endpoint.port,
327
- config.agent_run_id
328
- )
350
+ logger.info(
351
+ 'Connected to %s:%d with agent run ID %s.',
352
+ methods.connect.endpoint.host,
353
+ methods.connect.endpoint.port,
354
+ config.agent_run_id
355
+ )
329
356
 
330
- // Log "Reporting to..." message from connect response.
331
- if (config.messages) {
332
- config.messages.forEach((element) => {
333
- logger.info(element.message)
334
- })
335
- }
357
+ // Log "Reporting to..." message from connect response.
358
+ if (config.messages) {
359
+ config.messages.forEach((element) => {
360
+ logger.info(element.message)
361
+ })
362
+ }
336
363
 
337
- // Store request headers for future collector requests if they're present
338
- collector._reqHeadersMap = config.request_headers_map
364
+ // Store request headers for future collector requests if they're present
365
+ this._reqHeadersMap = config.request_headers_map
339
366
 
340
- // pass configuration data from the API so automatic reconnect works
341
- agent.reconfigure(config)
367
+ // pass configuration data from the API so automatic reconnect works
368
+ agent.reconfigure(config)
342
369
 
343
- callback(null, res)
344
- }
370
+ callback(null, res)
345
371
  }
346
372
 
347
373
  /**
@@ -379,13 +405,15 @@ CollectorAPI.prototype.reportSettings = function reportSettings(callback) {
379
405
  *
380
406
  * @param {Array} errors The encoded errors list.
381
407
  * @param {Function} callback The continuation / error handler.
408
+ * @returns {void}
382
409
  */
383
410
  CollectorAPI.prototype.error_data = function errorData(errors, callback) {
384
411
  if (!callback) {
385
412
  this._throwCallbackError()
386
413
  }
387
414
  if (!errors) {
388
- return callback(new TypeError('must pass errors to send'))
415
+ callback(new TypeError('must pass errors to send'))
416
+ return
389
417
  }
390
418
 
391
419
  this._sendData(this._methods.errors, errors, callback)
@@ -396,23 +424,27 @@ CollectorAPI.prototype.error_event_data = function errorEvents(events, callback)
396
424
  this._throwCallbackError()
397
425
  }
398
426
  if (!events) {
399
- return callback(new TypeError('must pass errors to send'))
427
+ callback(new TypeError('must pass errors to send'))
428
+ return
400
429
  }
401
430
 
402
431
  this._sendData(this._methods.errorEvents, events, callback)
403
432
  }
404
433
 
405
434
  CollectorAPI.prototype.analytic_event_data = transactionEvents
435
+
406
436
  /**
407
- * @param events
408
- * @param callback
437
+ * @param {Array} events list of events to send to collector
438
+ * @param {Function} callback handler on response
439
+ * @returns {void}
409
440
  */
410
441
  function transactionEvents(events, callback) {
411
442
  if (!callback) {
412
443
  this._throwCallbackError()
413
444
  }
414
445
  if (!events) {
415
- return callback(new TypeError('must pass events to send'))
446
+ callback(new TypeError('must pass events to send'))
447
+ return
416
448
  }
417
449
 
418
450
  this._sendData(this._methods.events, events, callback)
@@ -423,7 +455,8 @@ CollectorAPI.prototype.custom_event_data = function customEvents(events, callbac
423
455
  this._throwCallbackError()
424
456
  }
425
457
  if (!events) {
426
- return callback(new TypeError('must pass events to send'))
458
+ callback(new TypeError('must pass events to send'))
459
+ return
427
460
  }
428
461
 
429
462
  this._sendData(this._methods.customEvents, events, callback)
@@ -450,7 +483,8 @@ CollectorAPI.prototype.metric_data = function metricData(metrics, callback) {
450
483
  this._throwCallbackError()
451
484
  }
452
485
  if (!metrics) {
453
- return callback(new TypeError('must pass metrics to send'))
486
+ callback(new TypeError('must pass metrics to send'))
487
+ return
454
488
  }
455
489
 
456
490
  this._sendData(this._methods.metrics, metrics, callback)
@@ -473,7 +507,8 @@ CollectorAPI.prototype.sql_trace_data = function queryData(queries, callback) {
473
507
  this._throwCallbackError()
474
508
  }
475
509
  if (!queries) {
476
- return callback(new TypeError('must pass queries to send'))
510
+ callback(new TypeError('must pass queries to send'))
511
+ return
477
512
  }
478
513
  this._sendData(this._methods.queryData, queries, callback)
479
514
  }
@@ -483,7 +518,8 @@ CollectorAPI.prototype.span_event_data = function spanEvents(events, callback) {
483
518
  this._throwCallbackError()
484
519
  }
485
520
  if (!events) {
486
- return callback(new TypeError('must pass spans to send'))
521
+ callback(new TypeError('must pass spans to send'))
522
+ return
487
523
  }
488
524
  this._sendData(this._methods.spanEvents, events, callback)
489
525
  }
@@ -503,16 +539,18 @@ CollectorAPI.prototype.span_event_data = function spanEvents(events, callback) {
503
539
  * @param {Function} callback The continuation / error handler.
504
540
  */
505
541
  CollectorAPI.prototype.transaction_sample_data = transactionSampleData
542
+
506
543
  /**
507
- * @param traces
508
- * @param callback
544
+ * @param {Array} traces list of traces to send
545
+ * @param {Function} callback handler on response
509
546
  */
510
547
  function transactionSampleData(traces, callback) {
511
548
  if (!callback) {
512
549
  this._throwCallbackError()
513
550
  }
514
551
  if (!traces) {
515
- return callback(new TypeError('must pass traces to send'))
552
+ callback(new TypeError('must pass traces to send'))
553
+ return
516
554
  }
517
555
 
518
556
  this._sendData(this._methods.traces, traces, callback)
@@ -527,16 +565,16 @@ function transactionSampleData(traces, callback) {
527
565
  * 1. An array of logs.
528
566
  * 2. A list of common attributes(optional).
529
567
  *
530
- * @param {Array} logsRecords The encoded log entries.
531
- * @param logRecords
532
- * @param {Function} callback The continuation / error handler.
568
+ * @param {Array} logRecords The encoded log entries.
569
+ * @param {Function} callback The continuation / error handler.
533
570
  */
534
571
  CollectorAPI.prototype.log_event_data = function logEventData(logRecords, callback) {
535
572
  if (!callback) {
536
573
  this._throwCallbackError()
537
574
  }
538
575
  if (!logRecords) {
539
- return callback(new TypeError('must pass logRecords to send'))
576
+ callback(new TypeError('must pass logRecords to send'))
577
+ return
540
578
  }
541
579
 
542
580
  this._sendData(this._methods.logEvents, logRecords, callback)
@@ -546,8 +584,7 @@ CollectorAPI.prototype.log_event_data = function logEventData(logRecords, callba
546
584
  * Sends no data aside from the message itself. Clears the run ID, which
547
585
  * effectively disconnects the agent from the collector.
548
586
  *
549
- * @param Function callback Runs after the run ID has been cleared.
550
- * @param callback
587
+ * @param {Function} callback Runs after the run ID has been cleared.
551
588
  */
552
589
  CollectorAPI.prototype.shutdown = function shutdown(callback) {
553
590
  if (!callback) {
@@ -560,8 +597,8 @@ CollectorAPI.prototype.shutdown = function shutdown(callback) {
560
597
  this._methods.shutdown.invoke(null, this._reqHeadersMap, onShutdown)
561
598
 
562
599
  /**
563
- * @param error
564
- * @param response
600
+ * @param {Error} error response error
601
+ * @param {http.ServerResponse} response response from collector
565
602
  */
566
603
  function onShutdown(error, response) {
567
604
  if (error) {
@@ -599,7 +636,8 @@ CollectorAPI.prototype._runLifecycle = function _runLifecycle(method, body, call
599
636
  const api = this
600
637
  method.invoke(body, this._reqHeadersMap, function standardHandler(error, response) {
601
638
  if (error) {
602
- return callback(error)
639
+ callback(error)
640
+ return
603
641
  }
604
642
 
605
643
  return api._handleResponseCode(response, method.name, callback)
@@ -674,60 +712,55 @@ CollectorAPI.prototype.isConnected = function isConnected() {
674
712
  return !!this._agent.config.run_id
675
713
  }
676
714
 
715
+ CollectorAPI.prototype._handleResponseCode = _handleResponseCode
716
+
677
717
  /**
678
718
  * Returns appropriate CollectorResponse object according to response code.
679
719
  *
680
- * @param {object} response
720
+ * @param {http.ServerResponse} response response from collector
681
721
  * @param {number} response.status - Status code from collector response
682
722
  * @param {object} response.payload - Parsed response body, if any
683
723
  * @param {string} endpoint - Collector endpoint name
684
724
  * @param {Function} cb - CollectorAPI method invocation callback
685
725
  */
686
- CollectorAPI.prototype._handleResponseCode = _handleResponseCode
687
- /**
688
- * @param response
689
- * @param endpoint
690
- * @param cb
691
- */
692
726
  function _handleResponseCode(response, endpoint, cb) {
693
727
  const code = response.status
694
728
 
695
729
  /* eslint-disable padded-blocks */
696
730
  if (SUCCESS.has(code)) {
697
731
  // The request was a success!
698
- return setImmediate(cb, null, CollectorResponse.success(response.payload))
732
+ setImmediate(cb, null, CollectorResponse.success(response.payload))
699
733
  } else if (RESTART.has(code)) {
700
734
  // The agent needs to disconnect and restart.
701
735
  logFailure(endpoint, code, 'Restarting')
702
- return setImmediate(cb, null, CollectorResponse.reconnect(0, null))
736
+ setImmediate(cb, null, CollectorResponse.reconnect(0, null))
703
737
  } else if (FAILURE_DISCARD_DATA.has(code)) {
704
738
  // Something was wrong with our payload so we must delete our data.
705
739
  logFailure(endpoint, code, 'Discarding harvest data')
706
- return setImmediate(cb, null, CollectorResponse.discard(null))
740
+ setImmediate(cb, null, CollectorResponse.discard(null))
707
741
  } else if (FAILURE_SAVE_DATA.has(code)) {
708
742
  // Something was wrong with the request, but it wasn't our fault. We'll try again.
709
743
  logFailure(endpoint, code, 'Retaining data for next harvest')
710
- return setImmediate(cb, null, CollectorResponse.error(response.payload))
744
+ setImmediate(cb, null, CollectorResponse.error(response.payload))
711
745
  } else if (code === 410) {
712
746
  // New Relic doesn't like us and we shouldn't try to talk to them any more.
713
747
  logFailure(endpoint, code, 'Disconnecting from New Relic')
714
748
 
715
- return this._agent.stop(function onShutdown() {
749
+ this._agent.stop(function onShutdown() {
716
750
  cb(null, CollectorResponse.fatal(response.payload))
717
751
  })
752
+ } else {
753
+ // We're not sure what New Relic is trying to tell us. Let's get rid of our
754
+ // data just in case it is our fault.
755
+ logger.error('Agent endpoint %s returned unexpected status %s.', endpoint, code)
756
+ setImmediate(cb, null, CollectorResponse.discard(null))
718
757
  }
719
- /* eslint-enable padded-blocks */
720
-
721
- // We're not sure what New Relic is trying to tell us. Let's get rid of our
722
- // data just in case it is our fault.
723
- logger.error('Agent endpoint %s returned unexpected status %s.', endpoint, code)
724
- return setImmediate(cb, null, CollectorResponse.discard(null))
725
758
  }
726
759
 
727
760
  /**
728
- * @param endpoint
729
- * @param code
730
- * @param action
761
+ * @param {string} endpoint called endpoint
762
+ * @param {string} code http status code
763
+ * @param {string} action describes collector action
731
764
  */
732
765
  function logFailure(endpoint, code, action) {
733
766
  logger.error('Agent endpoint %s returned %s status. %s.', endpoint, code, action)