newrelic 8.17.1 → 9.0.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.
@@ -17,7 +17,7 @@ const NAMES = require('../../metrics/names')
17
17
  const SHIM_SYMBOLS = require('../../shim/constants').SYMBOLS
18
18
 
19
19
  const DEFAULT_HOST = 'localhost'
20
- const DEFAULT_PORT = 80
20
+ const DEFAULT_HTTP_PORT = 80
21
21
  const DEFAULT_SSL_PORT = 443
22
22
 
23
23
  const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
@@ -27,9 +27,8 @@ const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
27
27
  *
28
28
  * @param {Agent} agent
29
29
  * @param {object} opts
30
- * @param {function} makeRequest
31
- *
32
- * @return {http.ClientRequest} The instrumented outbound request.
30
+ * @param {Function} makeRequest
31
+ * @returns {http.ClientRequest} The instrumented outbound request.
33
32
  */
34
33
  module.exports = function instrumentOutbound(agent, opts, makeRequest) {
35
34
  if (typeof opts === 'string') {
@@ -38,10 +37,12 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
38
37
  opts = copy.shallow(opts)
39
38
  }
40
39
 
40
+ const defaultPort =
41
+ !opts.protocol || opts.protocol === 'http:' ? DEFAULT_HTTP_PORT : DEFAULT_SSL_PORT
41
42
  let hostname = opts.hostname || opts.host || DEFAULT_HOST
42
43
  let port = opts.port || opts.defaultPort
43
44
  if (!port) {
44
- port = !opts.protocol || opts.protocol === 'http:' ? DEFAULT_PORT : DEFAULT_SSL_PORT
45
+ port = defaultPort
45
46
  }
46
47
 
47
48
  if (!hostname || port < 1) {
@@ -49,11 +50,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
49
50
  return makeRequest(opts)
50
51
  }
51
52
 
52
- // Technically we shouldn't append the port if this is an https request on 443
53
- // but due to legacy issues we can't do that without moving customer's cheese.
54
- //
55
- // TODO: Move customers cheese by not appending the default port for https.
56
- if (port && port !== DEFAULT_PORT) {
53
+ if (port && port !== defaultPort) {
57
54
  hostname += ':' + port
58
55
  }
59
56
 
@@ -159,8 +156,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
159
156
  * @param {TraceSegment} segment
160
157
  * @param {http.ClientRequest} req
161
158
  * @param {Error} error
162
- *
163
- * @return {bool} True if the error will be collected by New Relic.
159
+ * @returns {bool} True if the error will be collected by New Relic.
164
160
  */
165
161
  function handleError(segment, req, error) {
166
162
  if (req.listenerCount('error') > 0) {
File without changes
@@ -27,16 +27,7 @@ module.exports = function initialize(agent, hapi, moduleName, shim) {
27
27
  } else if (hapi.Server) {
28
28
  // Server.connection was removed in v17
29
29
  if (!hapi.Server.prototype.connection) {
30
- return require('./hapi/hapi-17')(agent, hapi, moduleName, shim)
31
- }
32
-
33
- // See if we can find the plugin class. This should be the super class of
34
- // Server and will cover more scenarios.
35
- const Plugin = hapi.Server.super_
36
- if (_isPluginClass(Plugin)) {
37
- wrapServer(shim, Plugin)
38
- } else {
39
- wrapServer(shim, hapi.Server)
30
+ return require('./hapi/hapi')(agent, hapi, moduleName, shim)
40
31
  }
41
32
  }
42
33
  }
@@ -251,19 +242,6 @@ function wrapMiddleware(shim, middleware, event) {
251
242
  return shim.recordMiddleware(middleware, spec)
252
243
  }
253
244
 
254
- function _isPluginClass(Plugin) {
255
- if (typeof Plugin !== 'function' || !Plugin.prototype) {
256
- return false
257
- }
258
-
259
- const proto = Plugin.prototype
260
- return (
261
- typeof proto.handler === 'function' &&
262
- typeof proto.route === 'function' &&
263
- typeof proto.ext === 'function'
264
- )
265
- }
266
-
267
245
  function wrapReply(wrap, reply, isPreHandler) {
268
246
  const isFinal = !isPreHandler
269
247
  // The only reply method that is actually used by pre-handlers is `response`. All
@@ -5,8 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const semver = require('semver')
9
-
10
8
  function getQuery(shim, original, name, args) {
11
9
  const config = args[0]
12
10
  let statement
@@ -22,12 +20,10 @@ function getQuery(shim, original, name, args) {
22
20
  }
23
21
 
24
22
  module.exports = function initialize(agent, pgsql, moduleName, shim) {
25
- const pgVersion = shim.require('./package.json').version
26
-
27
23
  shim.setDatastore(shim.POSTGRES)
24
+
28
25
  // allows for native wrapping to not happen if not necessary
29
26
  // when env var is true
30
-
31
27
  if (process.env.NODE_PG_FORCE_NATIVE) {
32
28
  return instrumentPGNative(pgsql)
33
29
  }
@@ -36,7 +32,7 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
36
32
  // As of pg v7.0.0, Client.query returns a Promise from an async call.
37
33
  // pg supports event based Client.query when a Query object is passed in,
38
34
  // and works similarly in pg version <7.0.0
39
- if (semver.satisfies(pgVersion, '>=7.0.0') && typeof queryArgs[0] === 'string') {
35
+ if (typeof queryArgs[0] === 'string') {
40
36
  return {
41
37
  callback: shim.LAST,
42
38
  query: getQuery,
@@ -58,18 +54,7 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
58
54
  // wrapping for native
59
55
  function instrumentPGNative(pg) {
60
56
  shim.wrapReturn(pg, 'Client', clientFactoryWrapper)
61
- shim.wrapReturn(pg.pools, 'Client', clientFactoryWrapper)
62
-
63
- // In pg v5 the Client class used by pg-pool is the same Client
64
- // class as pg.Client. Since querying through the Pool class just
65
- // defers to Client.query in this case we should skip instrumenting
66
- // the Client class on Pool.
67
- // Note: pg v5 was the only version to have both the Pool
68
- // constructor and pg.pools so we can check against pg.pools to only
69
- // instrument pg.Pool on v6 and later.
70
- if (!pg.pools) {
71
- shim.wrapClass(pg, 'Pool', { post: poolPostConstructor, es6: true })
72
- }
57
+ shim.wrapClass(pg, 'Pool', { post: poolPostConstructor, es6: true })
73
58
  }
74
59
 
75
60
  function poolPostConstructor(shim) {
@@ -21,7 +21,6 @@ module.exports = function instrumentations() {
21
21
  'generic-pool': { type: MODULE_TYPE.GENERIC },
22
22
  '@grpc/grpc-js': { module: './instrumentation/grpc-js' },
23
23
  '@hapi/hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
24
- 'hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
25
24
  'ioredis': { type: MODULE_TYPE.DATASTORE },
26
25
  'koa': { module: '@newrelic/koa' },
27
26
  'memcached': { type: MODULE_TYPE.DATASTORE },
@@ -36,7 +35,6 @@ module.exports = function instrumentations() {
36
35
  'restify': { type: MODULE_TYPE.WEB_FRAMEWORK },
37
36
  'superagent': { module: '@newrelic/superagent' },
38
37
  'undici': { type: MODULE_TYPE.TRANSACTION },
39
- 'oracle': { type: null },
40
38
  'vision': { type: MODULE_TYPE.WEB_FRAMEWORK },
41
39
  'when': { type: null },
42
40
  'winston': { type: MODULE_TYPE.GENERIC }
@@ -147,13 +147,6 @@ const CASSANDRA = {
147
147
  ALL: DB.PREFIX + 'Cassandra/' + ALL
148
148
  }
149
149
 
150
- const ORACLE = {
151
- PREFIX: 'Oracle',
152
- STATEMENT: DB.STATEMENT + '/Oracle/',
153
- OPERATION: DB.OPERATION + '/Oracle/',
154
- INSTANCE: DB.INSTANCE + '/Oracle/'
155
- }
156
-
157
150
  const EXPRESS = {
158
151
  PREFIX: 'Expressjs/',
159
152
  MIDDLEWARE: MIDDLEWARE.PREFIX + 'Expressjs/',
@@ -280,7 +273,8 @@ const LOGGING = {
280
273
  WARN: `${LOGGING_LINES_PREFIX}/WARN`,
281
274
  ERROR: `${LOGGING_LINES_PREFIX}/ERROR`,
282
275
  DEBUG: `${LOGGING_LINES_PREFIX}/DEBUG`,
283
- TRACE: `${LOGGING_LINES_PREFIX}/TRACE`
276
+ TRACE: `${LOGGING_LINES_PREFIX}/TRACE`,
277
+ UNKNOWN: `${LOGGING_LINES_PREFIX}/UNKNOWN`
284
278
  },
285
279
  LIBS: {
286
280
  PINO: `${SUPPORTABILITY.LOGGING}/${NODEJS.PREFIX}pino/enabled`,
@@ -329,7 +323,6 @@ module.exports = {
329
323
  MYSQL: MYSQL,
330
324
  NODEJS: NODEJS,
331
325
  NORMALIZED: 'NormalizedUri',
332
- ORACLE: ORACLE,
333
326
  OTHER_TRANSACTION: OTHER_TRANSACTION,
334
327
  POSTGRES: POSTGRES,
335
328
  QUEUETIME: 'WebFrontend/QueueTime',
@@ -4,7 +4,6 @@
4
4
  */
5
5
 
6
6
  'use strict'
7
- const a = require('async')
8
7
  const logger = require('../../logger').child({ component: 'Transaction Trace Aggregator' })
9
8
 
10
9
  /*
@@ -185,16 +184,29 @@ class TransactionTraceAggregator extends TraceAggregator {
185
184
  return [this.runId, traces.map((trace) => trace.generateJSONSync())]
186
185
  }
187
186
 
188
- _toPayload(callback) {
187
+ async _toPayload(callback) {
189
188
  const traces = this.getTraces()
190
189
  if (!traces) {
191
190
  return callback(null, traces)
192
191
  }
193
- return a.map(
194
- traces,
195
- (trace, cb) => trace.generateJSON(cb),
196
- (err, encodedTraces) => callback(err, [this.runId, encodedTraces])
197
- )
192
+
193
+ const tracePromises = traces.map((trace) => {
194
+ return new Promise((resolve, reject) => {
195
+ trace.generateJSON((err, data) => {
196
+ if (err) {
197
+ reject(err)
198
+ }
199
+ resolve(data)
200
+ })
201
+ })
202
+ })
203
+
204
+ try {
205
+ const encodedTraces = await Promise.all(tracePromises)
206
+ callback(null, [this.runId, encodedTraces])
207
+ } catch (err) {
208
+ callback(err)
209
+ }
198
210
  }
199
211
 
200
212
  _afterSend(successful) {
@@ -5,7 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const async = require('async')
9
8
  const logger = require('../logger').child({ component: 'transaction-event-aggregator' })
10
9
  const EventAggregator = require('../aggregators/event-aggregator')
11
10
 
@@ -100,20 +99,19 @@ class TransactionEventAggregator extends EventAggregator {
100
99
  return rawEvent.value
101
100
  }
102
101
 
103
- _sendMultiple(eventPayloadPairs, sendCallback) {
102
+ async _sendMultiple(eventPayloadPairs, sendCallback) {
104
103
  const self = this
105
104
 
106
105
  // Send payloads one at a time
107
- async.eachOfSeries(
108
- eventPayloadPairs,
109
- (payloadPair, index, asyncCallback) => {
110
- logger.debug(
111
- 'Sending payload %d of %d to %s',
112
- index + 1,
113
- eventPayloadPairs.length,
114
- self.method
115
- )
116
-
106
+ const promises = eventPayloadPairs.map((payloadPair, index) => {
107
+ logger.debug(
108
+ 'Sending payload %d of %d to %s',
109
+ index + 1,
110
+ eventPayloadPairs.length,
111
+ self.method
112
+ )
113
+
114
+ return new Promise((resolve) => {
117
115
  self._sendSplitPayload(payloadPair.rawData, payloadPair.payload, (error) => {
118
116
  if (error) {
119
117
  logger.warn(error, 'An error occurred sending payload')
@@ -126,16 +124,16 @@ class TransactionEventAggregator extends EventAggregator {
126
124
  self.method
127
125
  )
128
126
 
129
- // don't pass on error, allow next payload to attempt to send
130
- asyncCallback()
127
+ // swallow error, allow all payloads to attempt to send
128
+ resolve()
131
129
  })
132
- },
133
- function afterAllPayloadsSent() {
134
- logger.debug('Finished sending %d payloads to %s', eventPayloadPairs.length, self.method)
130
+ })
131
+ })
135
132
 
136
- sendCallback()
137
- }
138
- )
133
+ await Promise.all(promises)
134
+ logger.debug('Finished sending %d payloads to %s', eventPayloadPairs.length, self.method)
135
+
136
+ sendCallback()
139
137
  }
140
138
 
141
139
  _sendSplitPayload(rawData, payload, callback) {
@@ -82,8 +82,10 @@ utils.isLogForwardingEnabled = function isLogForwardingEnabled(config, agent) {
82
82
  * @param {object} metrics metrics module
83
83
  */
84
84
  utils.incrementLoggingLinesMetrics = function incrementLoggingLinesMetrics(level, metrics) {
85
+ const levelMetric = getLogLevel(level)
86
+
85
87
  metrics.getOrCreateMetric(LOGGING.LINES).incrementCallCount()
86
- metrics.getOrCreateMetric(LOGGING.LEVELS[level.toUpperCase()]).incrementCallCount()
88
+ metrics.getOrCreateMetric(levelMetric).incrementCallCount()
87
89
  }
88
90
 
89
91
  /**
@@ -95,3 +97,14 @@ utils.incrementLoggingLinesMetrics = function incrementLoggingLinesMetrics(level
95
97
  utils.createModuleUsageMetric = function createModuleUsageMetric(lib, metrics) {
96
98
  metrics.getOrCreateMetric(LOGGING.LIBS[lib.toUpperCase()]).incrementCallCount()
97
99
  }
100
+
101
+ function getLogLevel(level) {
102
+ if (!level) {
103
+ return LOGGING.LEVELS.UNKNOWN
104
+ }
105
+ const logLevel = LOGGING.LEVELS[level.toUpperCase()]
106
+ if (!logLevel) {
107
+ return LOGGING.LEVELS.UNKNOWN
108
+ }
109
+ return logLevel
110
+ }
@@ -7,5 +7,7 @@
7
7
 
8
8
  const copy = require('./copy')
9
9
  const fs = require('fs')
10
+ const fsPromises = require('fs/promises')
10
11
 
11
12
  exports.fs = copy.shallow(fs)
13
+ exports.fsPromises = copy.shallow(fsPromises)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "8.17.1",
3
+ "version": "9.0.2",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [
@@ -108,6 +108,11 @@
108
108
  "name": "Diana Thayer",
109
109
  "email": "dthayer@newrelic.com",
110
110
  "web": "https://newrelic.com"
111
+ },
112
+ {
113
+ "name": "Jordi Gutiérrez Hermoso",
114
+ "email": "jgutierrezhermoso@newrelic.com",
115
+ "web": "https://newrelic.com"
111
116
  }
112
117
  ],
113
118
  "description": "New Relic agent",
@@ -121,7 +126,7 @@
121
126
  ],
122
127
  "homepage": "https://github.com/newrelic/node-newrelic",
123
128
  "engines": {
124
- "node": ">=12.0.0",
129
+ "node": ">=14",
125
130
  "npm": ">=6.0.0"
126
131
  },
127
132
  "directories": {
@@ -129,11 +134,10 @@
129
134
  },
130
135
  "scripts": {
131
136
  "bench": "node ./bin/run-bench.js",
132
- "ca-gen": "./bin/update-ca-bundle.sh",
133
137
  "docker-env": "./bin/docker-env-vars.sh",
134
138
  "docs": "npm ci && jsdoc -c ./jsdoc-conf.json --private -r .",
135
139
  "integration": "npm run prepare-test && npm run sub-install && time tap test/integration/**/**/*.tap.js --timeout=180 --no-coverage --reporter classic",
136
- "prepare-test": "npm run ca-gen && npm run ssl && npm run docker-env",
140
+ "prepare-test": "npm run ssl && npm run docker-env",
137
141
  "lint": "eslint ./*.js lib test bin examples",
138
142
  "lint:fix": "eslint --fix, ./*.js lib test bin examples",
139
143
  "public-docs": "jsdoc -c ./jsdoc-conf.json --tutorials examples/shim api.js lib/shim/ lib/transaction/handle.js && cp examples/shim/*.png out/",
@@ -161,11 +165,10 @@
161
165
  "dependencies": {
162
166
  "@grpc/grpc-js": "^1.5.5",
163
167
  "@grpc/proto-loader": "^0.6.13",
164
- "@newrelic/aws-sdk": "^4.1.1",
165
- "@newrelic/koa": "^6.1.1",
166
- "@newrelic/superagent": "^5.1.0",
168
+ "@newrelic/aws-sdk": "^5.0.0",
169
+ "@newrelic/koa": "^7.0.0",
170
+ "@newrelic/superagent": "^6.0.0",
167
171
  "@tyriar/fibonacci-heap": "^2.0.7",
168
- "async": "^3.2.3",
169
172
  "concat-stream": "^2.0.0",
170
173
  "https-proxy-agent": "^5.0.0",
171
174
  "json-stringify-safe": "^5.0.0",
@@ -174,19 +177,17 @@
174
177
  "winston-transport": "^4.5.0"
175
178
  },
176
179
  "optionalDependencies": {
177
- "@newrelic/native-metrics": "^8.0.0"
180
+ "@newrelic/native-metrics": "^9.0.0"
178
181
  },
179
182
  "devDependencies": {
180
183
  "@newrelic/eslint-config": "^0.0.3",
181
184
  "@newrelic/newrelic-oss-cli": "^0.1.2",
182
185
  "@newrelic/proxy": "^2.0.0",
183
- "@newrelic/test-utilities": "^6.5.5",
186
+ "@newrelic/test-utilities": "^7.0.0",
184
187
  "@octokit/rest": "^18.0.15",
185
188
  "@slack/bolt": "^3.7.0",
186
189
  "ajv": "^6.12.6",
187
- "architect": "*",
188
- "benchmark": "^2.1.4",
189
- "bluebird": "^3.4.7",
190
+ "async": "^3.2.4",
190
191
  "chai": "^4.1.2",
191
192
  "commander": "^7.0.0",
192
193
  "eslint": "^7.32.0",
@@ -197,22 +198,18 @@
197
198
  "eslint-plugin-node": "^11.1.0",
198
199
  "eslint-plugin-prettier": "^3.4.0",
199
200
  "express": "*",
200
- "generic-pool": "^3.6.1",
201
201
  "glob": "^7.1.2",
202
202
  "got": "^11.8.5",
203
203
  "husky": "^6.0.0",
204
204
  "jsdoc": "^3.6.3",
205
205
  "lint-staged": "^11.0.0",
206
206
  "memcached": ">=0.2.8",
207
- "minami": "^1.1.1",
208
- "mongodb": "^3.3.3",
209
- "mysql": "*",
207
+ "minami": "^1.2.3",
210
208
  "nock": "11.8.0",
211
209
  "prettier": "^2.3.2",
212
210
  "proxyquire": "^1.8.0",
213
211
  "q": "*",
214
- "redis": "^1.0.0",
215
- "request": "^2.88.0",
212
+ "request": "^2.88.2",
216
213
  "rimraf": "^2.6.3",
217
214
  "should": "*",
218
215
  "sinon": "^4.5.0",