newrelic 5.8.0 → 5.11.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.
package/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  All components of this product are
2
- Copyright (c) 2008-2016 New Relic, Inc. All rights reserved.
2
+ Copyright (c) 2012-2019 New Relic, Inc. All rights reserved.
3
3
 
4
4
  Certain inventions disclosed in this file may be claimed within
5
5
  patents owned or patent applications filed by New Relic, Inc. or third
@@ -293,14 +293,3 @@ party, nor do they have any authority to bind the other party by contract or
293
293
  otherwise to any obligation.
294
294
 
295
295
  Root Certificate License Agreement v3.0 (January 2014)
296
-
297
-
298
- The New Relic Node.js agent also uses code from the following open source
299
- projects under the following licenses:
300
-
301
- async http://opensource.org/licenses/MIT
302
- concat-stream http://opensource.org/licenses/MIT
303
- https-proxy-agent http://opensource.org/licenses/MIT
304
- json-stringify-safe http://opensource.org/licenses/ISC
305
- readable-stream http://opensource.org/licenses/MIT
306
- semver http://opensource.org/licenses/ISC
package/NEWS.md CHANGED
@@ -1,3 +1,106 @@
1
+ ### 5.11.0 (2019-07-29):
2
+
3
+ * Implements Expected and Ignored Errors functionality
4
+
5
+ * Bumps jsdoc and lodash dev dependency to avoid upstream vulnerability warning.
6
+
7
+ * Added support for scoped package name introduced in hapi v18 (@hapi/hapi).
8
+
9
+ This will provide functionality at parity with instrumentation for hapi v17. Any
10
+ new features may not yet be supported.
11
+
12
+ Huge shoutout to Aori Nevo (@aorinevo) for this contribution.
13
+
14
+ * Fixed bug where agent would count errors towards error metrics even if they were
15
+ dropped due to the error collector being disabled.
16
+
17
+ * The agent will now properly track cached paths to files in loaded modules on Node
18
+ versions >10.
19
+
20
+ As of Node v11, the path to a file in a module being loaded will only be resolved
21
+ on the first load; subsequent resolution of that file will use a cached value.
22
+ The agent records this resolved path and uses it for relative file look ups in
23
+ order to deep link into modules using `Shim#require`. Since the agent couldn't
24
+ reliably get at the path on the subsequent calls to require, it now replicates
25
+ the caching logic and hold onto the resolved path for a given file.
26
+
27
+ * Adds detailed logging through harvest/collector code to increase supportability.
28
+
29
+ ### 5.10.0 (2019-06-11):
30
+
31
+ * The agent now allows installation on node v11 and v12.
32
+
33
+ This change relaxes the engines restriction to include Node v11 and v12. This does
34
+ not constitute official support for those versions, and users on those versions
35
+ may run into subtle incompatibilities. For those users who are interested in
36
+ experimenting with the agent on v11 and v12, we are tracking relevant issues
37
+ here: https://github.com/newrelic/node-newrelic/issues/279.
38
+
39
+ * Lambda invocations ended with promises will now be recorded properly.
40
+
41
+ Previously, the lambda instrumentation was not intercepting the promise
42
+ resolution/rejection returned from a lambda handler. The instrumentation now
43
+ properly observes the promise, and ends the transaction when the promise has
44
+ finished.
45
+
46
+ * Lambda invocations will only attempt to end the related transaction a single time.
47
+
48
+ In the event of two lambda response events (e.g. callback called, and a promise
49
+ returned), the agent would attempt to end the transaction twice, producing an
50
+ extraneous empty payload. The agent now limits itself to a single end call for
51
+ a given transaction.
52
+
53
+ * The agent will now properly end transactions in the face of uncaught exceptions
54
+ while in serverless mode.
55
+
56
+ * Enables ability to migrate to Configurable Security Policies (CSP) on a per agent
57
+ basis for accounts already using High Security Mode (HSM).
58
+
59
+ When both HSM and CSP are enabled for an account, an agent (this version or later)
60
+ can successfully connect with either `high_security: true` or the appropriate
61
+ `security_policies_token` configured. `high_security` has been added as part of
62
+ the preconnect payload.
63
+
64
+ ### 5.9.1 (2019-05-28):
65
+
66
+ * moved third party notices to `THIRD_PARTY_NOTICES.md`
67
+
68
+ * Shim#require will now operate as expected.
69
+
70
+ Previously, the module interception code made the faulty assumption that a module's
71
+ filepath would be resolved before the module load call was invoked. This caused
72
+ the wrap filepath to be attributed to the modules being instrumented. This meant
73
+ that attempted relative require calls using Shim#require would resolved from the
74
+ incorrect path. The logic has been changed to keep a stack of the resolved
75
+ filepaths, resolving the issue.
76
+
77
+ * Updates error message for license check to indicate all places that need to be
78
+ updated.
79
+
80
+ * Shim#wrapReturn now uses ES6 proxies to wrap its methods.
81
+
82
+ This will accurately propagate look up and assignment onto the underlying wrapped
83
+ function, while maintaining all previous functionality.
84
+
85
+ * Updated versioned test configurations to reflect current engine support.
86
+
87
+ ### 5.9.0 (2019-05-20):
88
+
89
+ * Removed older versions of Cassandra from versioned tests
90
+
91
+ * For debug/test runs, shimmer will now cleanup the __NR_shim property on
92
+ instrumented methods. This leftover property did not result in any negative
93
+ behaviors but cleaning up for thoroughness and to prevent potential confusion.
94
+
95
+ * `serverless_mode` feature flag is now enabled by default.
96
+
97
+ * Fixes `recordMiddleware` promise parenting for certain cases where child segments
98
+ are created within resolving middleware `next()` promises.
99
+
100
+ * Added `instrumentLoadedModule` function to the API, allowing end-users to manually
101
+ apply an instrumentation to a loaded module. Useful for cases where some module
102
+ needs to be loaded before newrelic
103
+
1
104
  ### 5.8.0 (2019-05-06):
2
105
 
3
106
  * Modifies `MiddlewareSpec` route property to allow functions. Defers route
@@ -0,0 +1,239 @@
1
+ # Third Party Notices
2
+
3
+ The New Relic Node Agent uses source code from third party libraries which carry
4
+ their own copyright notices and license terms. These notices are provided
5
+ below.
6
+
7
+ In the event that a required notice is missing or incorrect, please notify us
8
+ by e-mailing [open-source@newrelic.com](mailto:open-source@newrelic.com).
9
+
10
+ For any licenses that require the disclosure of source code, the source code
11
+ can be found at https://github.com/newrelic/node-newrelic.
12
+
13
+ ## Contents
14
+
15
+ * [async](#async)
16
+ * [concat-stream](#concat-steam)
17
+ * [https-proxy-agent](#https-proxy-agent)
18
+ * [json-stringify-safe](#json-stringify-safe)
19
+ * [readable-stream](#readable-stream)
20
+ * [semver](#semver)
21
+
22
+ ## async
23
+
24
+ This product includes source derived from
25
+ [async](https://github.com/caolan/async), distributed under the
26
+ [MIT license](https://github.com/caolan/async/blob/a0b2be5a7add90d74e1337621be536ab01b584ae/LICENSE):
27
+
28
+ ```
29
+ Copyright (c) 2010-2018 Caolan McMahon
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ of this software and associated documentation files (the "Software"), to deal
33
+ in the Software without restriction, including without limitation the rights
34
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ copies of the Software, and to permit persons to whom the Software is
36
+ furnished to do so, subject to the following conditions:
37
+
38
+ The above copyright notice and this permission notice shall be included in
39
+ all copies or substantial portions of the Software.
40
+
41
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ THE SOFTWARE.
48
+
49
+ ```
50
+
51
+ ## concat-stream
52
+
53
+ This product includes source derived from
54
+ [async](https://github.com/maxogden/concat-stream), distributed under the
55
+ [MIT license](https://github.com/maxogden/concat-stream/blob/ceaa101bd2e19c5878a98dd6cb875108f49bf5c5/LICENSE):
56
+
57
+ ```
58
+ The MIT License
59
+
60
+ Copyright (c) 2013 Max Ogden
61
+
62
+ Permission is hereby granted, free of charge,
63
+ to any person obtaining a copy of this software and
64
+ associated documentation files (the "Software"), to
65
+ deal in the Software without restriction, including
66
+ without limitation the rights to use, copy, modify,
67
+ merge, publish, distribute, sublicense, and/or sell
68
+ copies of the Software, and to permit persons to whom
69
+ the Software is furnished to do so,
70
+ subject to the following conditions:
71
+
72
+ The above copyright notice and this permission notice
73
+ shall be included in all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
76
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
77
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
78
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
79
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
80
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
81
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
82
+ ```
83
+
84
+ ## https-proxy-agent
85
+
86
+ This product includes source derived from
87
+ [https-proxy-agent](https://github.com/TooTallNate/node-https-proxy-agent), distributed under the
88
+ [MIT license](https://github.com/TooTallNate/node-https-proxy-agent):
89
+
90
+ ```
91
+ (The MIT License)
92
+
93
+ Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
94
+
95
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
96
+
97
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
98
+
99
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
100
+
101
+ ```
102
+
103
+ ## json-stringify-safe
104
+
105
+ This product includes source derived from
106
+ [json-stringify-safe](https://github.com/moll/json-stringify-safe), distributed under the
107
+ [ISC license](https://github.com/moll/json-stringify-safe/blob/5930d6e51c58cf3a134f36301b029408bcfd09e5/LICENSE):
108
+
109
+ ```
110
+ The ISC License
111
+
112
+ Copyright (c) Isaac Z. Schlueter and Contributors
113
+
114
+ Permission to use, copy, modify, and/or distribute this software for any
115
+ purpose with or without fee is hereby granted, provided that the above
116
+ copyright notice and this permission notice appear in all copies.
117
+
118
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
119
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
120
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
121
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
122
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
123
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
124
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
125
+
126
+ ```
127
+
128
+ ## readable-stream
129
+
130
+ This product includes source derived from
131
+ [readable-stream](https://github.com/nodejs/readable-stream), distributed under the
132
+ [MIT license](https://github.com/nodejs/readable-stream/blob/4ba93f84cf8812ca2af793c7304a5c16de72088a/LICENSE):
133
+
134
+ ```
135
+ Node.js is licensed for use as follows:
136
+
137
+ """
138
+ Copyright Node.js contributors. All rights reserved.
139
+
140
+ Permission is hereby granted, free of charge, to any person obtaining a copy
141
+ of this software and associated documentation files (the "Software"), to
142
+ deal in the Software without restriction, including without limitation the
143
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
144
+ sell copies of the Software, and to permit persons to whom the Software is
145
+ furnished to do so, subject to the following conditions:
146
+
147
+ The above copyright notice and this permission notice shall be included in
148
+ all copies or substantial portions of the Software.
149
+
150
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
152
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
153
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
154
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
155
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
156
+ IN THE SOFTWARE.
157
+ """
158
+
159
+ This license applies to parts of Node.js originating from the
160
+ https://github.com/joyent/node repository:
161
+
162
+ """
163
+ Copyright Joyent, Inc. and other Node contributors. All rights reserved.
164
+ Permission is hereby granted, free of charge, to any person obtaining a copy
165
+ of this software and associated documentation files (the "Software"), to
166
+ deal in the Software without restriction, including without limitation the
167
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
168
+ sell copies of the Software, and to permit persons to whom the Software is
169
+ furnished to do so, subject to the following conditions:
170
+
171
+ The above copyright notice and this permission notice shall be included in
172
+ all copies or substantial portions of the Software.
173
+
174
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
177
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
178
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
179
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
180
+ IN THE SOFTWARE.
181
+ """
182
+
183
+ ```
184
+
185
+ ## semver
186
+
187
+ This product includes source derived from
188
+ [semver](https://github.com/npm/node-semver), distributed under the
189
+ [ISC license](https://github.com/npm/node-semver/blob/0e3bcedfb19e2f7ef64b9eb0a0f1554ed7d94be0/LICENSE):
190
+
191
+ ```
192
+ The ISC License
193
+
194
+ Copyright (c) Isaac Z. Schlueter and Contributors
195
+
196
+ Permission to use, copy, modify, and/or distribute this software for any
197
+ purpose with or without fee is hereby granted, provided that the above
198
+ copyright notice and this permission notice appear in all copies.
199
+
200
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
201
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
202
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
203
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
204
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
205
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
206
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
207
+ ```
208
+
209
+ ## @tyriar/fibonacci-heap
210
+
211
+ This product includes source derived from
212
+ [js-fibonacci-heap](https://github.com/gwtw/js-fibonacci-heap), distributed under the
213
+ [MIT license](https://github.com/gwtw/js-fibonacci-heap/blob/ec31d0966f9e54b0a52f3a074fe1d2442ab69979/LICENSE):
214
+
215
+ ```
216
+ The MIT License (MIT)
217
+
218
+ Copyright (c) 2014 Daniel Imms, http://www.growingwiththeweb.com
219
+
220
+ Permission is hereby granted, free of charge, to any person obtaining a copy
221
+ of this software and associated documentation files (the "Software"), to deal
222
+ in the Software without restriction, including without limitation the rights
223
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
224
+ copies of the Software, and to permit persons to whom the Software is
225
+ furnished to do so, subject to the following conditions:
226
+
227
+ The above copyright notice and this permission notice shall be included in
228
+ all copies or substantial portions of the Software.
229
+
230
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
231
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
232
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
233
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
234
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
235
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
236
+ THE SOFTWARE.
237
+ ```
238
+
239
+ Portions copyright [Node.js] contributors. Depending on your existing libraries and package management settings, your systems may call externally maintained libraries in addition to those listed above. See [here](https://nodejs.org/en/docs/meta/topics/dependencies/) and [here](https://github.com/nodejs/node/blob/v4.3.1/LICENSE) for additional details regarding externally maintained libraries and certain related licenses and notices.
package/api.js CHANGED
@@ -9,6 +9,7 @@ const hashes = require('./lib/util/hashes')
9
9
  const properties = require('./lib/util/properties')
10
10
  const stringify = require('json-stringify-safe')
11
11
  const shimmer = require('./lib/shimmer')
12
+ const shims = require('./lib/shim')
12
13
  const isValidType = require('./lib/util/attribute-types')
13
14
  const TransactionShim = require('./lib/shim/transaction-shim')
14
15
  const TransactionHandle = require('./lib/transaction/handle')
@@ -1197,6 +1198,57 @@ function instrumentDatastore(moduleName, onRequire, onError) {
1197
1198
  shimmer.registerInstrumentation(opts)
1198
1199
  }
1199
1200
 
1201
+ /**
1202
+ * Applies an instrumentation to an already loaded module.
1203
+ *
1204
+ * // oh no, express was loaded before newrelic
1205
+ * const express = require('express')
1206
+ * const newrelic = require('newrelic')
1207
+ *
1208
+ * // phew, we can use instrumentLoadedModule to make
1209
+ * // sure express is still instrumented
1210
+ * newrelic.instrumentLoadedModule('express', express)
1211
+ *
1212
+ * @param {string} moduleName
1213
+ * The module's name/identifier. Will be normalized
1214
+ * into an instrumentation key.
1215
+ *
1216
+ * @param {object} module
1217
+ * The actual module object or function we're instrumenting
1218
+ */
1219
+ API.prototype.instrumentLoadedModule =
1220
+ function instrumentLoadedModule(moduleName, module) {
1221
+ var metric = this.agent.metrics.getOrCreateMetric(
1222
+ NAMES.SUPPORTABILITY.API + '/instrumentLoadedModule'
1223
+ )
1224
+ metric.incrementCallCount()
1225
+
1226
+ const instrumentationName = shimmer.getInstrumentationNameFromModuleName(moduleName)
1227
+ if (!shimmer.registeredInstrumentations[instrumentationName]) {
1228
+ logger.warn("No instrumentation registered for '%s'.", instrumentationName)
1229
+ return false
1230
+ }
1231
+
1232
+ const instrumentation = shimmer.registeredInstrumentations[instrumentationName]
1233
+ if (!instrumentation.onRequire) {
1234
+ logger.warn("No onRequire function registered for '%s'.", instrumentationName)
1235
+ return false
1236
+ }
1237
+
1238
+ const resolvedName = require.resolve(moduleName)
1239
+
1240
+ const shim = shims.createShimFromType(
1241
+ instrumentation.type,
1242
+ this.agent,
1243
+ moduleName,
1244
+ resolvedName
1245
+ )
1246
+
1247
+ instrumentation.onRequire(shim, module, moduleName)
1248
+
1249
+ return true
1250
+ }
1251
+
1200
1252
  /**
1201
1253
  * Registers an instrumentation function.
1202
1254
  *
package/lib/agent.js CHANGED
@@ -218,6 +218,7 @@ Agent.prototype.stop = function stop(callback) {
218
218
  const agent = this
219
219
 
220
220
  this.setState('stopping')
221
+
221
222
  this._stopHarvester()
222
223
  sampler.stop()
223
224
 
@@ -234,6 +235,8 @@ Agent.prototype.stop = function stop(callback) {
234
235
  callback(error)
235
236
  })
236
237
  } else {
238
+ logger.trace('Collector was not connected, invoking callback.')
239
+
237
240
  process.nextTick(callback)
238
241
  }
239
242
  }
@@ -331,6 +334,8 @@ Agent.prototype.reset = function reset() {
331
334
  * struggling.
332
335
  */
333
336
  Agent.prototype.harvest = function harvest(callback) {
337
+ logger.trace('Peparing to harvest.')
338
+
334
339
  if (!callback) {
335
340
  throw new TypeError('callback required!')
336
341
  }
@@ -338,7 +343,10 @@ Agent.prototype.harvest = function harvest(callback) {
338
343
  // Generate metrics for this harvest and then check we are connected to the
339
344
  // collector.
340
345
  this._generateHarvestMetrics()
346
+
341
347
  if (!this.collector.isConnected()) {
348
+ logger.trace('Collector not connected.')
349
+
342
350
  return setImmediate(function immediatelyError() {
343
351
  callback(new Error('Not connected to New Relic!'))
344
352
  })
@@ -346,6 +354,8 @@ Agent.prototype.harvest = function harvest(callback) {
346
354
 
347
355
  // We have a connection, create a new harvest.
348
356
  this.emit('harvestStarted')
357
+ logger.info('Harvest started.')
358
+
349
359
  this._lastHarvest = new Harvest(this)
350
360
  this._lastHarvest.prepare(Harvest.ALL_ENDPOINTS)
351
361
 
@@ -355,30 +365,40 @@ Agent.prototype.harvest = function harvest(callback) {
355
365
  // Send the harvest!
356
366
  const collector = this.collector
357
367
  const agent = this
368
+
369
+ logger.trace('Sending harvest data...')
358
370
  this._lastHarvest.send(function afterHarvest(err, agentRunAction) {
359
371
  // Do we need to do anything to the agent run?
360
372
  if (agentRunAction === AGENT_RUN_BEHAVIOR.SHUTDOWN) {
361
373
  agent.emit('harvestFinished')
374
+ logger.info('Harvest finished. Shutdown requested.')
375
+
362
376
  agent.stop(function afterStop(stopError) {
363
377
  const shutdownError = stopError || err
364
378
  callback(shutdownError)
365
379
  })
366
380
  } else if (agentRunAction === AGENT_RUN_BEHAVIOR.RESTART) {
381
+ logger.info('Restart requested. Harvest will complete upon restart finish.')
382
+
367
383
  collector.restart(function afterRestart(restartError) {
368
384
  // TODO: What if preconnect/connect respond with shutdown here?
369
385
  if (restartError) {
370
386
  logger.warn('Failed to restart agent run after harvest')
371
387
  callback(restartError)
372
388
  } else {
389
+ logger.trace('Restart succeeded. Finishing harvest.')
373
390
  _finish(err)
374
391
  }
375
392
  })
376
393
  } else {
394
+ logger.trace('Data sent successfully. Finishing harvest.')
377
395
  _finish(err)
378
396
  }
379
397
 
380
398
  function _finish(error) {
381
399
  agent.emit('harvestFinished')
400
+ logger.info('Harvest finished.')
401
+
382
402
  agent._scheduleHarvester(agent.config.data_report_period)
383
403
  callback(error)
384
404
  }
@@ -391,16 +411,20 @@ Agent.prototype.harvest = function harvest(callback) {
391
411
  * NOTE: this doesn't currently work outside of serverless mode.
392
412
  */
393
413
  Agent.prototype.harvestSync = function harvestSync() {
414
+ logger.trace('Peparing to harvest.')
415
+
394
416
  // Generate metrics for this harvest and then check we are connected to the
395
417
  // collector.
396
418
  this._generateHarvestMetrics()
397
419
 
398
420
  if (!this.collector.isConnected()) {
399
- throw new Error('Not connected to New Relic!')
421
+ throw new Error('Sync harvest not connected/enabled!')
400
422
  }
401
423
 
402
424
  // We have a connection, create a new harvest.
403
425
  this.emit('harvestStarted')
426
+ logger.info('Harvest started.')
427
+
404
428
  this._lastHarvest = new Harvest(this)
405
429
  this._lastHarvest.prepare(Harvest.ALL_ENDPOINTS)
406
430
 
@@ -414,7 +438,9 @@ Agent.prototype.harvestSync = function harvestSync() {
414
438
  const payloads = this._lastHarvest.getPayloads()
415
439
  collector.populateDataSync(payloads)
416
440
  collector.flushPayloadSync()
441
+
417
442
  agent.emit('harvestFinished')
443
+ logger.info('Harvest finished.')
418
444
  }
419
445
 
420
446
  Agent.prototype._generateHarvestMetrics = function _generateHarvestMetrics() {
@@ -489,7 +515,7 @@ Agent.prototype.setState = function setState(newState) {
489
515
  throw new TypeError('Invalid state ' + newState)
490
516
  }
491
517
 
492
- logger.debug('Agent state changed from %s to %s.', this._state, newState)
518
+ logger.info('Agent state changed from %s to %s.', this._state, newState)
493
519
  this._state = newState
494
520
  this.emit(this._state)
495
521
  }
@@ -541,6 +567,8 @@ function _harvesterIntervalChange(interval, callback) {
541
567
  * @param {number} harvestSeconds How many seconds between harvests.
542
568
  */
543
569
  Agent.prototype._restartHarvester = function _restartHarvester(harvestSeconds) {
570
+ logger.trace('Restarting harvester.')
571
+
544
572
  this._stopHarvester()
545
573
  this._scheduleHarvester(harvestSeconds)
546
574
  }
@@ -549,6 +577,8 @@ Agent.prototype._restartHarvester = function _restartHarvester(harvestSeconds) {
549
577
  * Safely stop the harvest cycle timer.
550
578
  */
551
579
  Agent.prototype._stopHarvester = function _stopHarvester() {
580
+ logger.trace('Stopping harvester.')
581
+
552
582
  if (this.harvesterHandle) {
553
583
  clearTimeout(this.harvesterHandle)
554
584
  }
@@ -569,11 +599,17 @@ Agent.prototype._scheduleHarvester = function _scheduleHarvester(harvestSeconds)
569
599
 
570
600
  // If there was a previous harvest, we want to schedule the next one based on
571
601
  // its start time.
572
- if (this._lastHarvest && this._lastHarvest.startTime) {
602
+ const lastHarvestStart = this._lastHarvest && this._lastHarvest.startTime
603
+ if (lastHarvestStart) {
573
604
  const timeSinceHarvest = Date.now() - this._lastHarvest.startTime
574
605
  harvestDelay = Math.max(0, harvestDelay - timeSinceHarvest)
575
606
  }
576
607
 
608
+ logger.trace(
609
+ 'Scheduling harvester. ' +
610
+ `Last harvest start: ${lastHarvestStart}. Next harvest delay: ${harvestDelay}`
611
+ )
612
+
577
613
  this.harvesterHandle = setTimeout(function doHarvest() {
578
614
  // Agent#harvest handles scheduling the next harvest and properly reacting to
579
615
  // any errors or commands. All we need to do is note any errors it spits out.
@@ -583,6 +619,7 @@ Agent.prototype._scheduleHarvester = function _scheduleHarvester(harvestSeconds)
583
619
  }
584
620
  })
585
621
  }, harvestDelay)
622
+
586
623
  this.harvesterHandle.unref()
587
624
  }
588
625
 
@@ -735,7 +772,13 @@ Agent.prototype._transactionFinished = function _transactionFinished(transaction
735
772
  logger.debug('Explicitly not ignoring %s (%s).', transaction.name, transaction.id)
736
773
  }
737
774
  this.metrics.merge(transaction.metrics)
738
- this.errors.onTransactionFinished(transaction, this.metrics)
775
+ let collectedErrors = this.errors.onTransactionFinished(transaction)
776
+
777
+ // the metric should be incremented only if the error was actually collected
778
+ if (collectedErrors > 0) {
779
+ this.metrics.getOrCreateMetric(NAMES.ERRORS.PREFIX + transaction.getFullName())
780
+ .incrementCallCount(collectedErrors)
781
+ }
739
782
  this.traces.add(transaction)
740
783
 
741
784
  const trace = transaction.trace
@@ -73,6 +73,8 @@ CollectorAPI.prototype.connect = function connect(callback) {
73
73
  throw new TypeError('callback is required')
74
74
  }
75
75
 
76
+ logger.trace('Starting collector.')
77
+
76
78
  this._agent.setState('connecting')
77
79
 
78
80
  const api = this
@@ -146,9 +148,12 @@ CollectorAPI.prototype._login = function _login(callback) {
146
148
  var agent = this._agent
147
149
  var self = this
148
150
 
149
- var payload = agent.config.security_policies_token
150
- ? [{ security_policies_token: agent.config.security_policies_token }]
151
- : null
151
+ const preconnectData = { high_security: agent.config.high_security }
152
+ if (agent.config.security_policies_token) {
153
+ preconnectData.security_policies_token = agent.config.security_policies_token
154
+ }
155
+
156
+ const payload = [preconnectData]
152
157
 
153
158
  methods.redirect.invoke(payload, onPreConnect)
154
159
 
@@ -419,6 +424,8 @@ CollectorAPI.prototype.shutdown = function shutdown(callback) {
419
424
  throw new TypeError('callback is required')
420
425
  }
421
426
 
427
+ logger.info('Shutting down collector.')
428
+
422
429
  var agent = this._agent
423
430
  this._methods.shutdown.invoke(null, this._reqHeadersMap, onShutdown)
424
431
 
@@ -439,6 +446,8 @@ CollectorAPI.prototype.shutdown = function shutdown(callback) {
439
446
  }
440
447
 
441
448
  CollectorAPI.prototype.restart = function restart(callback) {
449
+ logger.info('Restarting collector.')
450
+
442
451
  var api = this
443
452
  this.shutdown(function reconnect() {
444
453
  api.connect(callback)
@@ -64,6 +64,8 @@ class ServerlessCollector {
64
64
  * @param {Function} cb The callback to invoke upon disabling the collector.
65
65
  */
66
66
  shutdown(cb) {
67
+ logger.trace('Disabling serverless collector.')
68
+
67
69
  this.enabled = false
68
70
  setImmediate(cb, null, CollectorResponse.success(null))
69
71
  }
@@ -298,7 +298,13 @@ exports.config = () => ({
298
298
  * your own server's sake. The payload of events is compressed, but if it
299
299
  * grows too large the New Relic servers may reject it.
300
300
  */
301
- max_event_samples_stored: 100
301
+ max_event_samples_stored: 100,
302
+
303
+ expected_classes: [],
304
+ expected_messages: {},
305
+ expected_status_codes: [],
306
+ ignore_classes:[],
307
+ ignore_messages:{}
302
308
  },
303
309
  /**
304
310
  * Error message redaction