newrelic 8.7.1 → 8.9.1

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/NEWS.md CHANGED
@@ -1,3 +1,97 @@
1
+ ### v8.9.1 (2022-03-22)
2
+
3
+ * Fixed `shim.wrapReturn` to call `Reflect.construct` in construct Proxy trap. Also including `newTarget` to work with inherited classes.
4
+
5
+ * Added link to New Relic Node.js Examples repository.
6
+
7
+ * Excluded installing dependencies in `versioned-external` folders when running integration tests.
8
+
9
+ ### v8.9.0 (2022-03-15)
10
+
11
+ * Added support for `initializeUnorderedBulkOp`, and `initializeOrderedBulkOp` in mongodb v3 instrumentation.
12
+
13
+ Thanks to Denis Lantsman (@dlants) for the contribution.
14
+
15
+ * Updated logger to delay logging until configuration is parsed. The logger will now queue all log entries that occur before the agent can parse the configuration.
16
+
17
+ Thanks to Cody Landry (@codylandry) for the contribution.
18
+
19
+ * Added `NEW_RELIC_ALLOW_ALL_HEADERS` as a boolean environment variable, same behavior as existing `allow_all_headers`.
20
+
21
+ * Updated the AWS IMDBS v2 endpoint to use `latest` to align with the internal agent specification.
22
+
23
+ * Bumped `@newrelic/koa` to ^6.1.1.
24
+
25
+ * Added Next.js to External Modules list in README.
26
+
27
+ * Updated mysql and mysql2 versioned tests to run against their own databases on the MySQL instance.
28
+
29
+ * Removed upper-bound testing from restify versioned tests so future major versions will be covered.
30
+
31
+ * Removed upper-bound testing from mysql2 versioned tests to cover existing and future major versions.
32
+
33
+ Continues to skip version 1.6.2 which had a bug that broke tests which was resolved in 1.6.3.
34
+
35
+ * Updated @hapi/hapi Node 16 versioned test runs to run against @hapi/hapi >=20.1.2 so future major releases will be ran.
36
+
37
+ * Fixed sparse checkout of non-default branch for external versioned tests.
38
+
39
+ * Added external versioned tests for the Apollo Server plugin instrumentation.
40
+
41
+ * Added nock delay to test timeouts in utilization integration tests.
42
+
43
+ * Added newrelic-node-nextjs to external versioned tests to be run on every PR.
44
+
45
+ * Updated external version test running to support more test scenarios.
46
+ * Adds `test/versioned-external` to lint ignore to avoid issues for scripts in tests that auto run linting tools (next/react).
47
+ * Adds `index.js` and `nr-hooks.js` to files automatically checked-out for test runs.
48
+
49
+ ### v8.8.0 (2022-02-23)
50
+
51
+ * Updated AWS metadata capture to utilize IMDSv2.
52
+
53
+ * Fixed link to discuss.newrelic.com in README
54
+
55
+ * Updated minimum Node version warning to output current Node version from process.
56
+
57
+ * Bumped `@newrelic/native-metrics` to ^7.1.1.
58
+
59
+ * Added `Nextjs` to a framework constant within the webframework-shim.
60
+
61
+ * Updated shim to pass active segment to inContext callback.
62
+
63
+ * Bumped `@grpc/grpc-js` to ^1.5.5.
64
+
65
+ * Bumped `@grpc/proto-loader` to ^0.6.9.
66
+
67
+ * Bumped `@newrelic/superagent` to ^5.1.0.
68
+
69
+ * Bumped `@newrelic/koa` to ^6.1.0.
70
+
71
+ * Bumped `async` to ^3.2.3.
72
+
73
+ * Resolved several npm audit warnings for dev deps.
74
+
75
+ * Fixed Post Release workflow by properly configuring git credentials so it can push API docs to branch
76
+ * Added `set -e` in publish docs script to exit on possible failures
77
+ * Removed redundant `npm ci` in publish API docs script
78
+
79
+ * Added ability to ignore certain PRs in `bin/pending-prs.js` report to slack
80
+
81
+ * Updated README to include `@newrelic/pino-enricher` as an external module.
82
+
83
+ * Fixed documentation in a sample of the Datastore Instrumentation for Node.js.
84
+
85
+ * Added a new `mongo:5` container to `npm run sevices` to test mongodb driver >=4.2.0.
86
+
87
+ * Fixed conditions in post release workflow to function when triggered via successful release and manual invoked.
88
+
89
+ * Updated method for retrieving agent version from repository by using `cat package.json | jq .version`
90
+
91
+ * Fixed minor formatting and spelling issues in `create-docs-pr.js`.
92
+
93
+ * Fixed an issue with the docs PR script that assumed `\n` in the NEWS.md file when extract version and release date
94
+
1
95
  ### v8.7.1 (2022-01-18)
2
96
 
3
97
  * Bumped @newrelic/aws-sdk to ^4.1.1.
package/README.md CHANGED
@@ -67,8 +67,10 @@ For more information on getting started, [check the Node.js docs](https://docs.n
67
67
  There are several modules that can be installed and configured to accompany the Node.js agent:
68
68
 
69
69
  * [@newrelic/apollo-server-plugin](https://github.com/newrelic/newrelic-node-apollo-server-plugin): New Relic's official Apollo Server plugin for use with the Node.js agent.
70
- * [@newrelic/winston-enricher](https://github.com/newrelic/newrelic-winston-logenricher-node): Provides distributed trace and span information output as JSON-formatted log messages. This is most commonly used with the New Relic Logs product.
70
+ * [@newrelic/winston-enricher](https://github.com/newrelic/newrelic-node-log-extensions/tree/main/packages/winston-log-enricher): Provides distributed trace and span information output as JSON-formatted log messages in Winston. This is most commonly used with the New Relic Logs product.
71
+ * [@newrelic/pino-enricher](https://github.com/newrelic/newrelic-node-log-extensions/tree/main/packages/pino-log-enricher): Provides distributed trace and span information output as JSON-formatted log messages in Pino. This is most commonly used with the New Relic Logs product.
71
72
  * [@newrelic/mysql](https://github.com/newrelic/node-newrelic-mysql)(**Experimental**): Standalone instrumentation for [mysql2](https://github.com/sidorares/node-mysql2#readme) and [mysql2/promise](https://github.com/sidorares/node-mysql2/blob/master/documentation/Promise-Wrapper.md) as well as the same instrumentation for [mysql](https://github.com/mysqljs/mysql#readme) within the Node.js agent.
73
+ * [@newrelic/next](https://github.com/newrelic/newrelic-node-nextjs): Provides instrumentation for the [Next.js](https://github.com/vercel/next.js/) npm package.
72
74
 
73
75
  There are several modules included within the Node.js agent to add more instrumentation for 3rd party modules:
74
76
 
@@ -143,6 +145,8 @@ Here are some resources for learning more about the agent:
143
145
 
144
146
  - [The changelog](https://github.com/newrelic/node-newrelic/blob/main/NEWS.md)
145
147
 
148
+ - [Example applications](https://github.com/newrelic/newrelic-node-examples) - Working examples of New Relic features in Node.js.
149
+
146
150
  ## Support
147
151
 
148
152
  Should you need assistance with New Relic products, you are in good hands with several support channels.
@@ -152,7 +156,7 @@ If the issue has been confirmed as a bug or is a feature request, please file a
152
156
  **Support Channels**
153
157
 
154
158
  * [New Relic Documentation](https://docs.newrelic.com/docs/agents/nodejs-agent/getting-started/introduction-new-relic-nodejs): Comprehensive guidance for using our platform
155
- * [New Relic Community](https://discuss.newrelic.com/c/support-products-agents/node-js-agent/): The best place to engage in troubleshooting questions
159
+ * [New Relic Community](https://discuss.newrelic.com/tags/c/telemetry-data-platform/agents/nodeagent): The best place to engage in troubleshooting questions
156
160
  * [New Relic Developer](https://developer.newrelic.com/): Resources for building a custom observability applications
157
161
  * [New Relic University](https://learn.newrelic.com/): A range of online training for New Relic users of every level
158
162
  * [New Relic Technical Support](https://support.newrelic.com/) 24/7/365 ticketed support. Read more about our [Technical Support Offerings](https://docs.newrelic.com/docs/licenses/license-information/general-usage-licenses/support-plan).
@@ -86,7 +86,7 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
86
86
 
87
87
  ### @grpc/grpc-js
88
88
 
89
- This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.3.7](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.3.7)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.3.7/LICENSE):
89
+ This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.5.5](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.5.5)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.5.5/LICENSE):
90
90
 
91
91
  ```
92
92
  Apache License
@@ -295,7 +295,7 @@ This product includes source derived from [@grpc/grpc-js](https://github.com/grp
295
295
 
296
296
  ### @grpc/proto-loader
297
297
 
298
- This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.5.6](https://github.com/grpc/grpc-node/tree/v0.5.6)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.5.6/LICENSE):
298
+ This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.6.9](https://github.com/grpc/grpc-node/tree/v0.6.9)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.6.9/LICENSE):
299
299
 
300
300
  ```
301
301
  Apache License
@@ -712,7 +712,7 @@ This product includes source derived from [@newrelic/aws-sdk](https://github.com
712
712
 
713
713
  ### @newrelic/koa
714
714
 
715
- This product includes source derived from [@newrelic/koa](https://github.com/newrelic/node-newrelic-koa) ([v6.0.1](https://github.com/newrelic/node-newrelic-koa/tree/v6.0.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-koa/blob/v6.0.1/LICENSE):
715
+ This product includes source derived from [@newrelic/koa](https://github.com/newrelic/node-newrelic-koa) ([v6.1.0](https://github.com/newrelic/node-newrelic-koa/tree/v6.1.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-koa/blob/v6.1.0/LICENSE):
716
716
 
717
717
  ```
718
718
  Apache License
@@ -921,7 +921,7 @@ Apache License
921
921
 
922
922
  ### @newrelic/superagent
923
923
 
924
- This product includes source derived from [@newrelic/superagent](https://github.com/newrelic/node-newrelic-superagent) ([v5.0.1](https://github.com/newrelic/node-newrelic-superagent/tree/v5.0.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-superagent/blob/v5.0.1/LICENSE):
924
+ This product includes source derived from [@newrelic/superagent](https://github.com/newrelic/node-newrelic-superagent) ([v5.1.0](https://github.com/newrelic/node-newrelic-superagent/tree/v5.1.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-superagent/blob/v5.1.0/LICENSE):
925
925
 
926
926
  ```
927
927
  Apache License
@@ -1159,7 +1159,7 @@ THE SOFTWARE.
1159
1159
 
1160
1160
  ### async
1161
1161
 
1162
- This product includes source derived from [async](https://github.com/caolan/async) ([v3.2.1](https://github.com/caolan/async/tree/v3.2.1)), distributed under the [MIT License](https://github.com/caolan/async/blob/v3.2.1/LICENSE):
1162
+ This product includes source derived from [async](https://github.com/caolan/async) ([v3.2.3](https://github.com/caolan/async/tree/v3.2.3)), distributed under the [MIT License](https://github.com/caolan/async/blob/v3.2.3/LICENSE):
1163
1163
 
1164
1164
  ```
1165
1165
  Copyright (c) 2010-2018 Caolan McMahon
@@ -2531,7 +2531,7 @@ SOFTWARE.
2531
2531
 
2532
2532
  ### jsdoc
2533
2533
 
2534
- This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v3.6.7](https://github.com/jsdoc/jsdoc/tree/v3.6.7)), distributed under the [Apache-2.0 License](https://github.com/jsdoc/jsdoc/blob/v3.6.7/LICENSE.md):
2534
+ This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v3.6.10](https://github.com/jsdoc/jsdoc/tree/v3.6.10)), distributed under the [Apache-2.0 License](https://github.com/jsdoc/jsdoc/blob/v3.6.10/LICENSE.md):
2535
2535
 
2536
2536
  ```
2537
2537
  # License
@@ -3377,7 +3377,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3377
3377
 
3378
3378
  ### @newrelic/native-metrics
3379
3379
 
3380
- This product includes source derived from [@newrelic/native-metrics](https://github.com/newrelic/node-native-metrics) ([v7.0.1](https://github.com/newrelic/node-native-metrics/tree/v7.0.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-native-metrics/blob/v7.0.1/LICENSE):
3380
+ This product includes source derived from [@newrelic/native-metrics](https://github.com/newrelic/node-native-metrics) ([v7.1.1](https://github.com/newrelic/node-native-metrics/tree/v7.1.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-native-metrics/blob/v7.1.1/LICENSE):
3381
3381
 
3382
3382
  ```
3383
3383
  Apache License
package/index.js CHANGED
@@ -45,10 +45,9 @@ function initialize() {
45
45
  logger.debug('Process was running %s seconds before agent was loaded.', preAgentTime)
46
46
 
47
47
  if (!psemver.satisfies(pkgJSON.engines.node)) {
48
- // TODO: Update this message when Node v12 is deprecated.
49
48
  message =
50
- 'New Relic for Node.js requires a version of Node equal to or\n' +
51
- 'greater than 12.0.0. Not starting!'
49
+ `New Relic for Node.js requires a version of Node ${pkgJSON.engines.node}. \n` +
50
+ `Please upgrade from your current Node version: ${process.version}. Not starting!`
52
51
 
53
52
  logger.error(message)
54
53
  throw new Error(message)
@@ -134,6 +134,8 @@ exports.config = () => ({
134
134
  * When true, all request headers except for those listed in attributes.exclude
135
135
  * will be captured for all traces, unless otherwise specified in a destination's
136
136
  * attributes include/exclude lists.
137
+ *
138
+ * @env NEW_RELIC_ALLOW_ALL_HEADERS
137
139
  */
138
140
  allow_all_headers: false,
139
141
 
package/lib/config/env.js CHANGED
@@ -21,6 +21,7 @@ const ENV_MAPPING = {
21
21
  proxy_user: 'NEW_RELIC_PROXY_USER',
22
22
  proxy_pass: 'NEW_RELIC_PROXY_PASS',
23
23
  agent_enabled: 'NEW_RELIC_ENABLED',
24
+ allow_all_headers: 'NEW_RELIC_ALLOW_ALL_HEADERS',
24
25
  attributes: {
25
26
  enabled: 'NEW_RELIC_ATTRIBUTES_ENABLED',
26
27
  exclude: 'NEW_RELIC_ATTRIBUTES_EXCLUDE',
@@ -206,6 +207,7 @@ const OBJECT_LIST_VARS = new Set(['NEW_RELIC_NAMING_RULES'])
206
207
  // fancy--just use 'true' and 'false', everybody.
207
208
  const BOOLEAN_VARS = new Set([
208
209
  'NEW_RELIC_ENABLED',
210
+ 'NEW_RELIC_ALLOW_ALL_HEADERS',
209
211
  'NEW_RELIC_ATTRIBUTES_ENABLED',
210
212
  'NEW_RELIC_ERROR_COLLECTOR_ENABLED',
211
213
  'NEW_RELIC_ERROR_COLLECTOR_ATTRIBUTES_ENABLED',
@@ -1623,7 +1623,8 @@ function initialize(config) {
1623
1623
  /**
1624
1624
  * When the logger is required here, it bootstraps itself and then
1625
1625
  * injects itself into this module's closure via setLogger on the
1626
- * instance of the logger it creates.
1626
+ * instance of the logger it creates. Logs are queued until config
1627
+ * has been loaded to apply logging settings to bootstrapping logs
1627
1628
  */
1628
1629
  logger = require('../logger')
1629
1630
 
@@ -1712,7 +1713,14 @@ function getOrCreateInstance() {
1712
1713
 
1713
1714
  // Config construction has potential to throw due to invalid settings.
1714
1715
  // This allows the agent to return a stub api without crashing the process.
1715
- _configInstance = Object.assign(defaultConfig(), { agent_enabled: false })
1716
+ _configInstance = Object.assign(defaultConfig(), {
1717
+ agent_enabled: false,
1718
+ logging: {
1719
+ enabled: true,
1720
+ filepath: 'stdout'
1721
+ }
1722
+ })
1723
+
1716
1724
  _configInstance.setLogger = Config.prototype.setLogger
1717
1725
  }
1718
1726
  }
@@ -43,6 +43,23 @@ common.instrumentCollection = function instrumentCollection(shim, Collection) {
43
43
  }
44
44
  }
45
45
 
46
+ /**
47
+ * Instruments the execute method on
48
+ * the BulkOperationBase class
49
+ *
50
+ * @param {Shim} shim
51
+ * @param {BulkOperationModule} bulk operation module, typically from mongodb/lib/bulk/common
52
+ * @param BulkOperationModule
53
+ */
54
+ common.instrumentBulkOperation = function instrumentBulkOperation(shim, BulkOperationModule) {
55
+ const BulkOperationBase = BulkOperationModule && BulkOperationModule.BulkOperationBase
56
+
57
+ if (BulkOperationBase && BulkOperationBase.prototype) {
58
+ const proto = BulkOperationBase.prototype
59
+ shim.recordBatchQuery(proto, 'execute', common.makeBulkDescFunc(shim, 'execute'))
60
+ }
61
+ }
62
+
46
63
  /**
47
64
  * Instruments all methods from constants.DB_OPS on
48
65
  * the Db class.
@@ -84,6 +101,25 @@ common.makeQueryDescFunc = function makeQueryDescFunc(shim, methodName) {
84
101
  }
85
102
  }
86
103
 
104
+ /**
105
+ * Sets up the desc for all instrumented bulk operations
106
+ *
107
+ * @param {Shim} shim
108
+ * @param {string} methodName
109
+ */
110
+ common.makeBulkDescFunc = function makeBulkDescFunc(shim) {
111
+ return function bulkDescFunc() {
112
+ const parameters = getInstanceAttributeParameters(shim, this)
113
+ return {
114
+ query: this.isOrdered ? 'orderedBulk' : 'unorderedBulk',
115
+ parameters,
116
+ promise: true,
117
+ callback: shim.LAST,
118
+ opaque: true
119
+ }
120
+ }
121
+ }
122
+
87
123
  /**
88
124
  * Sets up a listener for `started` on instrumenter(mongo APM). This applies to
89
125
  * mongo <4. The listener adds the following attributes to the active segment:
@@ -161,9 +197,10 @@ function setHostPort(shim, connStr, db, client) {
161
197
  * @param obj
162
198
  */
163
199
  function getInstanceAttributeParameters(shim, obj) {
164
- if (obj.s && obj.s.db && obj.s.topology) {
200
+ if (obj.s && obj.s.topology) {
165
201
  shim.logger.trace('Adding datastore instance attributes from obj.s.db + obj.s.topology')
166
- const databaseName = obj.s.db.databaseName || null
202
+ const databaseName =
203
+ (obj.s.db && obj.s.db.databaseName) || (obj.s.namespace && obj.s.namespace.db) || null
167
204
  const topology = obj.s.topology
168
205
  if (topology.s && topology.s.options) {
169
206
  return doCapture(topology.s.options, databaseName)
@@ -7,6 +7,7 @@
7
7
 
8
8
  const {
9
9
  captureAttributesOnStarted,
10
+ instrumentBulkOperation,
10
11
  instrumentCollection,
11
12
  instrumentCursor,
12
13
  instrumentDb,
@@ -27,6 +28,8 @@ function queryParser(operation) {
27
28
  collection = this.operation.target
28
29
  } else if (this.ns) {
29
30
  collection = this.ns.split(/\./)[1] || collection
31
+ } else if (this.s && this.s.collection && this.s.collection.collectionName) {
32
+ collection = this.s.collection.collectionName
30
33
  }
31
34
  return { operation, collection }
32
35
  }
@@ -68,6 +71,7 @@ module.exports = function instrument(shim, mongodb) {
68
71
  instrumentCursor(shim, mongodb.Cursor)
69
72
  instrumentCursor(shim, shim.require('./lib/aggregation_cursor'))
70
73
  instrumentCursor(shim, shim.require('./lib/command_cursor'))
74
+ instrumentBulkOperation(shim, shim.require('./lib/bulk/common'))
71
75
  instrumentCollection(shim, mongodb.Collection)
72
76
  instrumentDb(shim, mongodb.Db)
73
77
 
package/lib/logger.js CHANGED
@@ -9,12 +9,16 @@ const Logger = require('./util/logger')
9
9
  const fs = require('./util/unwrapped-core').fs
10
10
 
11
11
  // create bootstrapping logger
12
- module.exports = new Logger({
12
+ const logger = new Logger({
13
13
  name: 'newrelic_bootstrap',
14
- stream: process.stdout,
15
- level: 'info'
14
+ level: 'info',
15
+
16
+ // logger is configured below. Logs are queued until configured
17
+ configured: false
16
18
  })
17
19
 
20
+ module.exports = logger
21
+
18
22
  /**
19
23
  * Don't load config until this point, because it requires this
20
24
  * module, and if it gets loaded too early, module.exports will have no
@@ -28,8 +32,8 @@ if (config) {
28
32
  enabled: config.logging.enabled
29
33
  }
30
34
 
31
- // create the "real" logger
32
- module.exports = new Logger(options)
35
+ // configure logger
36
+ logger.configure(options)
33
37
 
34
38
  if (config.logging.enabled) {
35
39
  let stream
@@ -52,9 +56,6 @@ if (config) {
52
56
  /* eslint-enable no-console */
53
57
  })
54
58
  }
55
- module.exports.pipe(stream)
59
+ logger.pipe(stream)
56
60
  }
57
-
58
- // now tell the config module to switch to the real logger
59
- config.setLogger(module.exports)
60
61
  }
package/lib/shim/shim.js CHANGED
@@ -639,10 +639,9 @@ function wrapReturn(nodule, properties, spec, args) {
639
639
  }
640
640
  return true
641
641
  },
642
- construct: function constructTrap(Target, proxyArgs) {
643
- // Call the underlying function. If this was called as a constructor, call
644
- // the wrapped function as a constructor too.
645
- let ret = new Target(...proxyArgs)
642
+ construct: function constructTrap(target, proxyArgs, newTarget) {
643
+ // Call the underlying function via Reflect.
644
+ let ret = Reflect.construct(target, proxyArgs, newTarget)
646
645
 
647
646
  // Assemble the arguments to hand to the spec.
648
647
  const _args = [shim, fn, fnName, ret]
@@ -1307,7 +1306,7 @@ function applySegment(func, segment, full, context, args, inContextCB) {
1307
1306
  }
1308
1307
 
1309
1308
  if (typeof inContextCB === 'function') {
1310
- inContextCB()
1309
+ inContextCB(segment)
1311
1310
  }
1312
1311
 
1313
1312
  try {
@@ -29,10 +29,11 @@ const FRAMEWORK_NAMES = {
29
29
  CONNECT: 'Connect',
30
30
  DIRECTOR: 'Director',
31
31
  EXPRESS: 'Expressjs',
32
+ FASTIFY: 'Fastify',
32
33
  HAPI: 'Hapi',
33
34
  KOA: 'Koa',
34
- RESTIFY: 'Restify',
35
- FASTIFY: 'Fastify'
35
+ NEXT: 'Nextjs',
36
+ RESTIFY: 'Restify'
36
37
  }
37
38
 
38
39
  const MIDDLEWARE_TYPE_DETAILS = {
@@ -64,24 +65,19 @@ const TRANSACTION_INFO_KEY = '__NR_transactionInfo'
64
65
  * Constructs a shim associated with the given agent instance, specialized for
65
66
  * instrumenting web frameworks.
66
67
  *
67
- * @constructor
68
- * @extends TransactionShim
68
+ * @class
69
+ * @augments TransactionShim
69
70
  * @classdesc
70
71
  * A helper class for wrapping web framework modules.
71
- *
72
72
  * @param {Agent} agent
73
73
  * The agent this shim will use.
74
- *
75
74
  * @param {string} moduleName
76
75
  * The name of the module being instrumented.
77
- *
78
76
  * @param {string} resolvedName
79
77
  * The full path to the loaded module.
80
- *
81
78
  * @param {string} [frameworkId]
82
79
  * The name of the web framework being instrumented. If available, use one of
83
80
  * the values from {@link WebFrameworkShim.FRAMEWORK_NAMES}.
84
- *
85
81
  * @see TransactionShim
86
82
  * @see WebFrameworkShim.FRAMEWORK_NAMES
87
83
  */
@@ -130,123 +126,93 @@ WebFrameworkShim.prototype.captureUrlParams = captureUrlParams
130
126
 
131
127
  /**
132
128
  * @callback RouteParserFunction
133
- *
134
129
  * @summary
135
130
  * Called whenever new middleware are mounted using the instrumented framework,
136
131
  * this method should pull out a representation of the mounted path.
137
- *
138
132
  * @param {WebFrameworkShim} shim
139
133
  * The shim in use for this instrumentation.
140
- *
141
- * @param {function} fn
134
+ * @param {Function} fn
142
135
  * The function which received this route string/RegExp.
143
- *
144
136
  * @param {string} fnName
145
137
  * The name of the function to which this route was given.
146
- *
147
138
  * @param {string|RegExp} route
148
139
  * The route that was given to the function.
149
- *
150
- * @return {string|RegExp} The mount point from the given route.
140
+ * @returns {string|RegExp} The mount point from the given route.
151
141
  */
152
142
 
153
143
  /**
154
144
  * @callback RouteRequestFunction
155
- *
156
145
  * @summary
157
146
  * Extracts the request object from the arguments to the middleware function.
158
- *
159
147
  * @param {WebFrameworkShim} shim - The shim used for instrumentation.
160
- * @param {function} fn - The middleware function.
148
+ * @param {Function} fn - The middleware function.
161
149
  * @param {string} fnName - The name of the middleware function.
162
150
  * @param {Array} args - The arguments to the middleware function.
163
- *
164
- * @return {Object} The request object.
151
+ * @returns {object} The request object.
165
152
  */
166
153
 
167
154
  /**
168
155
  * @callback RouteNextFunction
169
- *
170
156
  * @summary
171
157
  * Used to wrap functions that users can call to continue to the next middleware.
172
- *
173
158
  * @param {WebFrameworkShim} shim - The shim used for instrumentation.
174
- * @param {function} fn - The middleware function.
159
+ * @param {Function} fn - The middleware function.
175
160
  * @param {string} fnName - The name of the middleware function.
176
161
  * @param {Array} args - The arguments to the middleware function.
177
162
  * @param {NextWrapperFunction} wrap - A function to wrap an individual next function.
178
- *
179
- * @return {Object} The request object.
163
+ * @returns {object} The request object.
180
164
  */
181
165
 
182
166
  /**
183
167
  * @callback RouteParameterFunction
184
- *
185
168
  * @summary
186
169
  * Extracts the route parameters from the arguments to the middleware function.
187
- *
188
170
  * @param {WebFrameworkShim} shim - The shim used for instrumentation.
189
- * @param {function} fn - The middleware function.
171
+ * @param {Function} fn - The middleware function.
190
172
  * @param {string} fnName - The name of the middleware function.
191
173
  * @param {Array} args - The arguments to the middleware function.
192
- *
193
- * @return {Object} A map of route parameter names to values.
174
+ * @returns {object} A map of route parameter names to values.
194
175
  */
195
176
 
196
177
  /**
197
178
  * @callback MiddlewareWrapperFunction
198
- *
199
179
  * @summary
200
180
  * Called for each middleware passed to a mounting method. Should perform the
201
181
  * wrapping of the middleware.
202
- *
203
182
  * @param {WebFrameworkShim} shim
204
183
  * The shim used for instrumentation.
205
- *
206
- * @param {function} middleware
184
+ * @param {Function} middleware
207
185
  * The middleware function to wrap.
208
- *
209
186
  * @param {string} fnName
210
187
  * The name of the middleware function.
211
- *
212
188
  * @param {string} [route=null]
213
189
  * The route the middleware is mounted on if one was found.
214
- *
215
190
  * @see WebFrameworkShim#recordMiddleware
216
191
  * @see WebFrameworkShim#recordParamware
217
192
  */
218
193
 
219
194
  /**
220
195
  * @interface MiddlewareSpec
221
- *
222
196
  * @description
223
197
  * Describes the interface for middleware functions with this instrumentation.
224
- *
225
198
  * @property {number|RouteRequestFunction} [req=shim.FIRST]
226
199
  * Indicates which argument to the middleware is the request object. It can also be
227
200
  * a function to extract the request object from the middleware arguments.
228
- *
229
201
  * @property {number} [res=shim.SECOND]
230
202
  * Indicates which argument to the middleware is the response object.
231
- *
232
203
  * @property {number|RouteNextFunction} [next=shim.THIRD]
233
204
  * Indicates which argument to the middleware function is the callback. When it is
234
205
  * a function, it will be called with the arguments of the middleware and a function
235
206
  * for wrapping calls that represent continuation from the current middleware.
236
- *
237
207
  * @property {string} [name]
238
208
  * The name to use for this middleware. Defaults to `middleware.name`.
239
- *
240
209
  * @property {RouteParameterFunction} [params]
241
210
  * A function to extract the route parameters from the middleware arguments.
242
211
  * Defaults to using `req.params`.
243
- *
244
212
  * @property {string} [type='MIDDLEWARE']
245
- *
246
- * @property {string|function} [route=null]
213
+ * @property {string | Function} [route=null]
247
214
  * Route/path used for naming segments and transaction name candidates. If a function,
248
215
  * will be invoked just before segment creation with middleware invocation.
249
- *
250
216
  * @property {boolean} [appendPath=true]
251
217
  * Indicates that the path associated with the middleware should be appended
252
218
  * and popped from the stack of name candidates.
@@ -254,31 +220,25 @@ WebFrameworkShim.prototype.captureUrlParams = captureUrlParams
254
220
 
255
221
  /**
256
222
  * @interface MiddlewareMounterSpec
257
- *
258
223
  * @description
259
224
  * Describes the arguments provided to mounting methods (e.g. `app.post()`).
260
- *
261
225
  * @property {number|string} [route=null]
262
226
  * Tells which argument may be the mounting path for the other arguments. If
263
227
  * the indicated argument is a function it is assumed the route was not provided
264
228
  * and the indicated argument is a middleware function. If a string is provided
265
229
  * it will be used as the mounting path.
266
- *
267
230
  * @property {MiddlewareWrapperFunction} [wrapper]
268
231
  * A function to call for each middleware function passed to the mounter.
269
232
  */
270
233
 
271
234
  /**
272
235
  * @interface RenderSpec
273
- * @extends RecorderSpec
274
- *
236
+ * @augments RecorderSpec
275
237
  * @description
276
238
  * Describes the interface for render methods.
277
- *
278
239
  * @property {number} [view=shim.FIRST]
279
240
  * Identifies which argument is the name of the view being rendered. Defaults
280
241
  * to {@link Shim#ARG_INDEXES shim.FIRST}.
281
- *
282
242
  * @see SegmentSpec
283
243
  * @see RecorderSpec
284
244
  */
@@ -292,7 +252,6 @@ WebFrameworkShim.prototype.captureUrlParams = captureUrlParams
292
252
  * - `setRouteParser(parser)`
293
253
  *
294
254
  * @memberof WebFrameworkShim.prototype
295
- *
296
255
  * @param {RouteParserFunction} parser - The parser function to use.
297
256
  */
298
257
  function setRouteParser(parser) {
@@ -310,10 +269,8 @@ function setRouteParser(parser) {
310
269
  * This should be the first thing the instrumentation does.
311
270
  *
312
271
  * @memberof WebFrameworkShim.prototype
313
- *
314
272
  * @param {WebFrameworkShim.FRAMEWORK_NAMES|string} framework
315
273
  * The name of the framework.
316
- *
317
274
  * @see WebFrameworkShim.FRAMEWORK_NAMES
318
275
  */
319
276
  function setFramework(framework) {
@@ -332,7 +289,6 @@ function setFramework(framework) {
332
289
  * Sets the URI path to be used for naming the transaction currently in scope.
333
290
  *
334
291
  * @memberof WebFrameworkShim.prototype
335
- *
336
292
  * @param {string} uri - The URI path to use for the transaction.
337
293
  */
338
294
  function setTransactionUri(uri) {
@@ -351,18 +307,14 @@ function setTransactionUri(uri) {
351
307
  * - `recordRender(func [, spec])`
352
308
  *
353
309
  * @memberof WebFrameworkShim.prototype
354
- *
355
- * @param {Object|Function} nodule
310
+ * @param {object | Function} nodule
356
311
  * The source for the properties to wrap, or a single function to wrap.
357
- *
358
312
  * @param {string|Array.<string>} [properties]
359
313
  * One or more properties to wrap. If omitted, the `nodule` parameter is
360
314
  * assumed to be the function to wrap.
361
- *
362
315
  * @param {RenderSpec} [spec]
363
316
  * The spec for wrapping the render method.
364
- *
365
- * @return {Object|Function} The first parameter to this function, after
317
+ * @returns {object | Function} The first parameter to this function, after
366
318
  * wrapping it or its properties.
367
319
  */
368
320
  function recordRender(nodule, properties, spec) {
@@ -407,20 +359,15 @@ function recordRender(nodule, properties, spec) {
407
359
  * - `wrapMiddlewareMounter(func [, spec])`
408
360
  *
409
361
  * @memberof WebFrameworkShim.prototype
410
- *
411
- * @param {Object|Function} nodule
362
+ * @param {object | Function} nodule
412
363
  * The source for the properties to wrap, or a single function to wrap.
413
- *
414
364
  * @param {string|Array.<string>} [properties]
415
365
  * One or more properties to wrap. If omitted, the `nodule` parameter is
416
366
  * assumed to be the function to wrap.
417
- *
418
367
  * @param {MiddlewareMounterSpec} [spec]
419
368
  * Spec describing the parameters for this middleware mount point.
420
- *
421
- * @return {Object|Function} The first parameter to this function, after
369
+ * @returns {object | Function} The first parameter to this function, after
422
370
  * wrapping it or its properties.
423
- *
424
371
  * @see WebFrameworkShim#recordMiddleware
425
372
  */
426
373
  function wrapMiddlewareMounter(nodule, properties, spec) {
@@ -470,6 +417,10 @@ function wrapMiddlewareMounter(nodule, properties, spec) {
470
417
  }
471
418
 
472
419
  _wrapMiddlewares.call(this, routeIdx, args)
420
+ /**
421
+ * @param _routeIdx
422
+ * @param middlewares
423
+ */
473
424
  function _wrapMiddlewares(_routeIdx, middlewares) {
474
425
  for (let i = 0; i < middlewares.length; ++i) {
475
426
  // If this argument is the route argument skip it.
@@ -512,20 +463,15 @@ function wrapMiddlewareMounter(nodule, properties, spec) {
512
463
  * - `recordMiddleware(func [, spec])`
513
464
  *
514
465
  * @memberof WebFrameworkShim.prototype
515
- *
516
- * @param {Object|Function} nodule
466
+ * @param {object | Function} nodule
517
467
  * The source for the properties to wrap, or a single function to wrap.
518
- *
519
468
  * @param {string|Array.<string>} [properties]
520
469
  * One or more properties to wrap. If omitted, the `nodule` parameter is
521
470
  * assumed to be the function to wrap.
522
- *
523
471
  * @param {MiddlewareSpec} [spec]
524
472
  * The spec for wrapping the middleware.
525
- *
526
- * @return {Object|Function} The first parameter to this function, after
473
+ * @returns {object | Function} The first parameter to this function, after
527
474
  * wrapping it or its properties.
528
- *
529
475
  * @see WebFrameworkShim#wrapMiddlewareMounter
530
476
  */
531
477
  function recordMiddleware(nodule, properties, spec) {
@@ -560,18 +506,14 @@ function recordMiddleware(nodule, properties, spec) {
560
506
  * processing as possible.
561
507
  *
562
508
  * @memberof WebFrameworkShim.prototype
563
- *
564
- * @param {Object|Function} nodule
509
+ * @param {object | Function} nodule
565
510
  * The source for the properties to wrap, or a single function to wrap.
566
- *
567
511
  * @param {string|Array.<string>} [properties]
568
512
  * One or more properties to wrap. If omitted, the `nodule` parameter is
569
513
  * assumed to be the function to wrap.
570
- *
571
514
  * @param {MiddlewareSpec} [spec]
572
515
  * The spec for wrapping the middleware.
573
- *
574
- * @return {Object|Function} The first parameter to this function, after
516
+ * @returns {object | Function} The first parameter to this function, after
575
517
  * wrapping it or its properties.
576
518
  */
577
519
  function recordParamware(nodule, properties, spec) {
@@ -610,10 +552,8 @@ function recordParamware(nodule, properties, spec) {
610
552
  * caught by the user.
611
553
  *
612
554
  * @memberof WebFrameworkShim.prototype
613
- *
614
555
  * @param {Request} req - The request which caused the error.
615
556
  * @param {*?} err - The error which has occurred.
616
- *
617
557
  * @see WebFrameworkShim#errorHandled
618
558
  * @see WebFrameworkShim#setErrorPredicate
619
559
  */
@@ -628,10 +568,8 @@ function noticeError(req, err) {
628
568
  * Indicates that the given error has been handled for this request.
629
569
  *
630
570
  * @memberof WebFrameworkShim.prototype
631
- *
632
571
  * @param {Request} req - The request which caused the error.
633
572
  * @param {*} err - The error which has been handled.
634
- *
635
573
  * @see WebFrameworkShim#noticeError
636
574
  * @see WebFrameworkShim#setErrorPredicate
637
575
  */
@@ -647,11 +585,9 @@ function errorHandled(req, err) {
647
585
  * an error.
648
586
  *
649
587
  * @memberof WebFrameworkShim.prototype
650
- *
651
588
  * @param {function(object): bool} pred
652
589
  * Function which should return true if the object passed to it is considered
653
590
  * an error.
654
- *
655
591
  * @see WebFrameworkShim#noticeError
656
592
  * @see WebFrameworkShim#errorHandled
657
593
  */
@@ -663,7 +599,6 @@ function setErrorPredicate(pred) {
663
599
  * Marks the current path as a potential responder.
664
600
  *
665
601
  * @memberof WebFrameworkShim.prototype
666
- *
667
602
  * @param {Request} req - The request which caused the error.
668
603
  */
669
604
  function savePossibleTransactionName(req) {
@@ -678,7 +613,6 @@ function savePossibleTransactionName(req) {
678
613
  * responded.
679
614
  *
680
615
  * @memberof WebFrameworkShim.prototype
681
- *
682
616
  * @param {function(args, object): bool} pred
683
617
  * Function which should return true if the object passed to it is considered
684
618
  * a response.
@@ -691,8 +625,7 @@ function setResponsePredicate(pred) {
691
625
  * Capture URL parameters from a request object as attributes of the current segment.
692
626
  *
693
627
  * @memberof WebFrameworkShim.prototype
694
- *
695
- * @param {Object} params
628
+ * @param {object} params
696
629
  * An object with key-value pairs.
697
630
  */
698
631
  function captureUrlParams(params) {
@@ -708,19 +641,14 @@ function captureUrlParams(params) {
708
641
  * Default route parser function if one is not provided.
709
642
  *
710
643
  * @private
711
- *
712
644
  * @param {WebFrameworkShim} shim
713
645
  * The shim in use for this instrumentation.
714
- *
715
- * @param {function} fn
646
+ * @param {Function} fn
716
647
  * The function which received this route string/RegExp.
717
- *
718
648
  * @param {string} fnName
719
649
  * The name of the function to which this route was given.
720
- *
721
650
  * @param {string|RegExp} route
722
651
  * The route that was given to the function.
723
- *
724
652
  * @see RouteParserFunction
725
653
  */
726
654
  function _defaultRouteParser(shim, fn, fnName, route) {
@@ -737,8 +665,7 @@ function _defaultRouteParser(shim, fn, fnName, route) {
737
665
  * Default error predicate just returns true.
738
666
  *
739
667
  * @private
740
- *
741
- * @return {bool} True. Always.
668
+ * @returns {bool} True. Always.
742
669
  */
743
670
  function _defaultErrorPredicate() {
744
671
  return true
@@ -748,8 +675,7 @@ function _defaultErrorPredicate() {
748
675
  * Default response predicate just returns false.
749
676
  *
750
677
  * @private
751
- *
752
- * @return {bool} False. Always.
678
+ * @returns {bool} False. Always.
753
679
  */
754
680
  function _defaultResponsePredicate() {
755
681
  return false
@@ -759,19 +685,18 @@ function _defaultResponsePredicate() {
759
685
  * Wraps the given function in a middleware recorder function.
760
686
  *
761
687
  * @private
762
- *
763
688
  * @param {WebFrameworkShim} shim
764
689
  * The shim used for this instrumentation.
765
- *
766
- * @param {function} middleware
690
+ * @param {Function} middleware
767
691
  * The middleware function to record.
768
- *
769
692
  * @param {MiddlewareSpec} spec
770
693
  * The spec describing the middleware.
771
- *
772
- * @return {function} The middleware function wrapped in a recorder.
694
+ * @returns {Function} The middleware function wrapped in a recorder.
773
695
  */
774
696
  function _recordMiddleware(shim, middleware, spec) {
697
+ /**
698
+ *
699
+ */
775
700
  function getRoute() {
776
701
  let route = spec.route || '/'
777
702
 
@@ -797,6 +722,9 @@ function _recordMiddleware(shim, middleware, spec) {
797
722
  metricName = shim._metrics.MIDDLEWARE + metricName + name
798
723
  }
799
724
 
725
+ /**
726
+ * @param route
727
+ */
800
728
  function getSegmentName(route) {
801
729
  let segmentName = metricName
802
730
  if (typeDetails.path) {
@@ -817,6 +745,12 @@ function _recordMiddleware(shim, middleware, spec) {
817
745
  )
818
746
 
819
747
  // TODO: let's please break these out
748
+ /**
749
+ * @param shim
750
+ * @param fn
751
+ * @param fnName
752
+ * @param args
753
+ */
820
754
  function middlewareWithCallbackRecorder(shim, fn, fnName, args) {
821
755
  const route = getRoute()
822
756
 
@@ -909,6 +843,12 @@ function _recordMiddleware(shim, middleware, spec) {
909
843
  }
910
844
  }
911
845
 
846
+ /**
847
+ * @param shim
848
+ * @param fn
849
+ * @param fnName
850
+ * @param args
851
+ */
912
852
  function middlewareWithPromiseRecorder(shim, fn, fnName, args) {
913
853
  const route = getRoute()
914
854
 
@@ -1007,6 +947,10 @@ function _recordMiddleware(shim, middleware, spec) {
1007
947
  }
1008
948
  }
1009
949
 
950
+ /**
951
+ * @param shim
952
+ * @param req
953
+ */
1010
954
  function _makeGetReq(shim, req) {
1011
955
  return function getReqFromArgs(shim, fn, name, args) {
1012
956
  const reqIdx = shim.normalizeIndex(args.length, req)
@@ -1018,6 +962,10 @@ function _makeGetReq(shim, req) {
1018
962
  }
1019
963
  }
1020
964
 
965
+ /**
966
+ * @param nextDetails
967
+ * @param txInfo
968
+ */
1021
969
  function _makeNextBinder(nextDetails, txInfo) {
1022
970
  return function bindNext(shim, fn, _name, segment, args) {
1023
971
  if (!segment) {
@@ -1029,6 +977,11 @@ function _makeNextBinder(nextDetails, txInfo) {
1029
977
 
1030
978
  // Called from outside to wrap functions that could be called to continue
1031
979
  // to the next middleware
980
+ /**
981
+ * @param nodule
982
+ * @param property
983
+ * @param isFinal
984
+ */
1032
985
  function nextWrapper(nodule, property, isFinal) {
1033
986
  shim.wrap(nodule, property, function wrapper(shim, original) {
1034
987
  const parentSegment = segment || shim.getSegment()
@@ -1077,11 +1030,9 @@ function _makeNextBinder(nextDetails, txInfo) {
1077
1030
  * available.
1078
1031
  *
1079
1032
  * @private
1080
- *
1081
1033
  * @param {WebFrameworkShim} shim - The shim used for this instrumentation.
1082
1034
  * @param {http.IncomingMessage} req - The incoming request object.
1083
- *
1084
- * @return {object?} The transaction information if available, otherwise null.
1035
+ * @returns {object?} The transaction information if available, otherwise null.
1085
1036
  */
1086
1037
  function _getTransactionInfo(shim, req) {
1087
1038
  try {
@@ -1096,8 +1047,8 @@ function _getTransactionInfo(shim, req) {
1096
1047
  * Creates a recorder for middleware metrics.
1097
1048
  *
1098
1049
  * @private
1099
- *
1100
- *
1050
+ * @param shim
1051
+ * @param metricName
1101
1052
  * @param {string} path - The mounting path of the middleware.
1102
1053
  * @param {Segment} segment - The segment generated for this middleware.
1103
1054
  * @param {string} scope - The scope of the metric to record.
@@ -1119,13 +1070,10 @@ function _makeMiddlewareRecorder(shim, metricName) {
1119
1070
  * Adds the given error to the transaction information if it is actually an error.
1120
1071
  *
1121
1072
  * @private
1122
- *
1123
1073
  * @param {WebFrameworkShim} shim
1124
1074
  * The shim used for this web framework.
1125
- *
1126
1075
  * @param {TransactionInfo} txInfo
1127
1076
  * The transaction context information for the request.
1128
- *
1129
1077
  * @param {*} err
1130
1078
  * The error to notice.
1131
1079
  */
@@ -1138,14 +1086,11 @@ function _noticeError(shim, txInfo, err) {
1138
1086
  * Determines if the given object is an error according to the shim.
1139
1087
  *
1140
1088
  * @private
1141
- *
1142
1089
  * @param {WebFrameworkShim} shim
1143
1090
  * The shim used for this web framework.
1144
- *
1145
1091
  * @param {?*} err
1146
1092
  * The object to check for error-ness.
1147
- *
1148
- * @return {bool} True if the given object is an error according to the shim.
1093
+ * @returns {bool} True if the given object is an error according to the shim.
1149
1094
  */
1150
1095
  function _isError(shim, err) {
1151
1096
  return err && shim._errorPredicate(err)
@@ -1155,11 +1100,9 @@ function _isError(shim, err) {
1155
1100
  * Copy the keys expected from source to destination.
1156
1101
  *
1157
1102
  * @private
1158
- *
1159
- * @param {Object} destination
1103
+ * @param {object} destination
1160
1104
  * The spec object receiving the expected values
1161
- *
1162
- * @param {Object} source
1105
+ * @param {object} source
1163
1106
  * The spec object the values are coming from
1164
1107
  */
1165
1108
  function _copyExpectedSpecParameters(destination, source) {
@@ -39,7 +39,8 @@ function Logger(options, extra) {
39
39
  const passedInLevel = this.coerce(options.level)
40
40
  this.options = {
41
41
  _level: passedInLevel,
42
- enabled: options.enabled === undefined ? true : options.enabled
42
+ enabled: options.enabled === undefined ? true : options.enabled,
43
+ configured: options.configured === undefined ? true : !!options.configured
43
44
  }
44
45
  this._nestedLog = false
45
46
  this.name = options.name
@@ -47,12 +48,30 @@ function Logger(options, extra) {
47
48
  this.extra = extra || Object.create(null)
48
49
  this.buffer = ''
49
50
  this.reading = false
51
+ this.logQueue = []
50
52
  if (options.stream) {
51
53
  this.pipe(options.stream)
52
54
  }
53
55
  }
54
56
  Logger.MAX_LOG_BUFFER = MAX_LOG_BUFFER
55
57
 
58
+ Logger.prototype.configure = function configure(options) {
59
+ if (options.name !== undefined) {
60
+ this.name = options.name
61
+ }
62
+
63
+ if (options.enabled !== undefined) {
64
+ this.options.enabled = options.enabled
65
+ }
66
+
67
+ if (options.level !== undefined) {
68
+ this.options._level = this.coerce(options.level)
69
+ }
70
+
71
+ this.options.configured = true
72
+ this._flushQueuedLogs()
73
+ }
74
+
56
75
  Logger.prototype.coerce = function coerce(value) {
57
76
  if (!isNaN(parseInt(value, 10)) && isFinite(value)) {
58
77
  // value is numeric
@@ -74,6 +93,11 @@ Object.keys(LEVELS).forEach(function buildLevel(_level) {
74
93
  const level = Logger.prototype.coerce(LEVELS[_level])
75
94
 
76
95
  function log(extra) {
96
+ if (!this.options.configured) {
97
+ this.logQueue.unshift({ level: _level, args: arguments })
98
+ return
99
+ }
100
+
77
101
  if (!this.options.enabled) {
78
102
  return false
79
103
  }
@@ -149,6 +173,13 @@ Object.keys(LEVELS).forEach(function buildLevel(_level) {
149
173
  }
150
174
  })
151
175
 
176
+ Logger.prototype._flushQueuedLogs = function _flushQueuedLogs() {
177
+ while (this.logQueue.length) {
178
+ const { level, args } = this.logQueue.shift()
179
+ this[level].apply(this, args)
180
+ }
181
+ }
182
+
152
183
  Object.assign(Logger.prototype, loggingFunctions)
153
184
 
154
185
  Logger.prototype.child = function child(extra) {
@@ -196,6 +227,10 @@ Logger.prototype._read = function _read() {
196
227
  * already converted the objects to strings.
197
228
  * Returns a boolean representing the status of the write
198
229
  * (success/failure)
230
+ *
231
+ * @param level
232
+ * @param args
233
+ * @param extra
199
234
  */
200
235
  Logger.prototype.write = function write(level, args, extra) {
201
236
  if (this._nestedLog) {
@@ -9,6 +9,7 @@ const logger = require('../logger.js').child({ component: 'aws-info' })
9
9
  const common = require('./common')
10
10
  const NAMES = require('../metrics/names.js')
11
11
  let results = null
12
+ const INSTANCE_HOST = '169.254.169.254'
12
13
 
13
14
  module.exports = fetchAWSInfo
14
15
  module.exports.clearCache = function clearAWSCache() {
@@ -24,27 +25,45 @@ function fetchAWSInfo(agent, callback) {
24
25
  return setImmediate(callback, null, results)
25
26
  }
26
27
 
27
- const instanceHost = '169.254.169.254'
28
- const apiVersion = '2016-09-02'
29
- const endpoint = 'dynamic/instance-identity/document'
30
- const url = 'http://' + instanceHost + '/' + apiVersion + '/' + endpoint
31
- common.request(url, agent, function getMetadata(err, data) {
28
+ const authTokenOpts = {
29
+ headers: { 'X-aws-ec2-metadata-token-ttl-seconds': '21600' },
30
+ host: INSTANCE_HOST,
31
+ method: 'PUT',
32
+ path: '/latest/api/token',
33
+ timeout: 500
34
+ }
35
+ common.request(authTokenOpts, agent, function getAuthToken(err, authToken) {
32
36
  if (err) {
37
+ logger.debug('Failed to get AWS auth token.')
33
38
  return callback(err)
34
39
  }
35
40
 
36
- try {
37
- data = JSON.parse(data)
38
- } catch (e) {
39
- logger.debug(e, 'Failed to parse AWS metadata.')
40
- data = null
41
+ const metadataOpts = {
42
+ headers: { 'X-aws-ec2-metadata-token': authToken },
43
+ host: INSTANCE_HOST,
44
+ method: 'GET',
45
+ path: '/latest/dynamic/instance-identity/document',
46
+ timeout: 500
41
47
  }
42
48
 
43
- results = common.getKeys(data, ['availabilityZone', 'instanceId', 'instanceType'])
44
- if (results == null) {
45
- logger.debug('AWS metadata was invalid.')
46
- agent.metrics.getOrCreateMetric(NAMES.UTILIZATION.AWS_ERROR).incrementCallCount()
47
- }
48
- callback(null, results)
49
+ common.request(metadataOpts, agent, function getMetadata(metaErr, data) {
50
+ if (metaErr) {
51
+ return callback(metaErr)
52
+ }
53
+
54
+ try {
55
+ data = JSON.parse(data)
56
+ } catch (e) {
57
+ logger.debug(e, 'Failed to parse AWS metadata.')
58
+ data = null
59
+ }
60
+
61
+ results = common.getKeys(data, ['availabilityZone', 'instanceId', 'instanceType'])
62
+ if (results == null) {
63
+ logger.debug('AWS metadata was invalid.')
64
+ agent.metrics.getOrCreateMetric(NAMES.UTILIZATION.AWS_ERROR).incrementCallCount()
65
+ }
66
+ callback(null, results)
67
+ })
49
68
  })
50
69
  }
@@ -65,6 +65,12 @@ exports.request = function request(opts, agent, cb) {
65
65
 
66
66
  opts.timeout = opts.timeout || 1000
67
67
 
68
+ // This can make more that GET requests if you pass in an object
69
+ // Node.js just pass this method into ClientRequest which accepts
70
+ // any valid HTTP Method
71
+ // see: https://github.com/nodejs/node/blob/master/lib/http.js#L106
72
+ // Technically this wouldn't work for a PUT/POST with a body
73
+ // but works fine in all cases where this is being used.
68
74
  const req = http.get(opts, function awsRequest(res) {
69
75
  res.pipe(concat(respond))
70
76
  function respond(data) {
@@ -89,9 +95,7 @@ exports.request = function request(opts, agent, cb) {
89
95
  }
90
96
  })
91
97
 
92
- req.setTimeout(1000, function requestTimeout() {
93
- req.abort()
94
- })
98
+ req.on('timeout', abortRequest)
95
99
 
96
100
  req.on('error', function requestError(err) {
97
101
  if (err.code === 'ECONNRESET') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "8.7.1",
3
+ "version": "8.9.1",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [
@@ -136,7 +136,7 @@
136
136
  "prepare-test": "npm run ca-gen && npm run ssl && npm run docker-env",
137
137
  "lint": "eslint ./*.js lib test bin examples",
138
138
  "lint:fix": "eslint --fix, ./*.js lib test bin examples",
139
- "public-docs": "npm ci && jsdoc -c ./jsdoc-conf.json --tutorials examples/shim api.js lib/shim/ lib/transaction/handle.js && cp examples/shim/*.png out/",
139
+ "public-docs": "jsdoc -c ./jsdoc-conf.json --tutorials examples/shim api.js lib/shim/ lib/transaction/handle.js && cp examples/shim/*.png out/",
140
140
  "publish-docs": "./bin/publish-docs.sh",
141
141
  "services": "./bin/docker-services.sh",
142
142
  "smoke": "npm run ssl && time tap test/smoke/**/**/*.tap.js --timeout=180 --no-coverage",
@@ -159,13 +159,13 @@
159
159
  "newrelic-naming-rules": "./bin/test-naming-rules.js"
160
160
  },
161
161
  "dependencies": {
162
- "@grpc/grpc-js": "^1.2.11",
163
- "@grpc/proto-loader": "^0.5.6",
162
+ "@grpc/grpc-js": "^1.5.5",
163
+ "@grpc/proto-loader": "^0.6.9",
164
164
  "@newrelic/aws-sdk": "^4.1.1",
165
- "@newrelic/koa": "^6.0.1",
166
- "@newrelic/superagent": "^5.0.1",
165
+ "@newrelic/koa": "^6.1.1",
166
+ "@newrelic/superagent": "^5.1.0",
167
167
  "@tyriar/fibonacci-heap": "^2.0.7",
168
- "async": "^3.2.0",
168
+ "async": "^3.2.3",
169
169
  "concat-stream": "^2.0.0",
170
170
  "https-proxy-agent": "^5.0.0",
171
171
  "json-stringify-safe": "^5.0.0",
@@ -173,7 +173,7 @@
173
173
  "semver": "^5.3.0"
174
174
  },
175
175
  "optionalDependencies": {
176
- "@newrelic/native-metrics": "^7.0.1"
176
+ "@newrelic/native-metrics": "^7.1.1"
177
177
  },
178
178
  "devDependencies": {
179
179
  "@newrelic/eslint-config": "^0.0.3",