newrelic 9.0.0 → 9.0.3

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.
@@ -5,9 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const a = require('async')
9
8
  const path = require('path')
10
- const fs = require('./util/unwrapped-core').fs
9
+ const { fsPromises } = require('./util/unwrapped-core')
11
10
  const os = require('os')
12
11
  const logger = require('./logger').child({ component: 'environment' })
13
12
  const stringify = require('json-stringify-safe')
@@ -31,8 +30,7 @@ let settings = Object.create(null)
31
30
  * Fetches the setting of the given name, defaulting to an empty array.
32
31
  *
33
32
  * @param {string} name - The name of the setting to look for.
34
- *
35
- * @return {Array.<string>} An array of values matching that name.
33
+ * @returns {Array.<string>} An array of values matching that name.
36
34
  */
37
35
  function getSetting(name) {
38
36
  return settings[name] || []
@@ -67,73 +65,47 @@ function clearSetting(name) {
67
65
  *
68
66
  * @param {string} root - Path to start listing packages from.
69
67
  * @param {Array} [packages=[]] - Array to append found packages to.
70
- * @param {function} callback - Callback function.
71
- *
72
- * @return {Array} List of packages.
73
68
  */
74
- function listPackages(root, packages, callback) {
75
- // listPackages(root, callback)
76
- if (typeof packages === 'function') {
77
- callback = packages
78
- packages = []
79
- }
69
+ async function listPackages(root, packages = []) {
80
70
  _log('Listing packages in %s', root)
81
71
 
82
- a.waterfall(
83
- [
84
- a.apply(fs.readdir, root),
85
- function iterateDirs(dirs, cb) {
86
- a.eachLimit(dirs, 2, forEachDir, cb)
87
- }
88
- ],
89
- function onAllDirsRead(err) {
90
- _log('Done listing packages in %s', root)
91
- if (err) {
92
- logger.trace(err, 'Could not list packages in %s (probably not an error)', root)
93
- return callback()
94
- }
95
- callback(null, packages)
96
- }
97
- )
72
+ try {
73
+ const dirs = await fsPromises.readdir(root)
74
+ await Promise.all(dirs.map(forEachDir))
75
+ _log('Done listing packages in %s', root)
76
+ } catch (err) {
77
+ logger.trace(err, 'Could not list packages in %s (probably not an error)', root)
78
+ }
98
79
 
99
- function forEachDir(dir, cb) {
80
+ async function forEachDir(dir) {
100
81
  _log('Checking package %s in %s', dir, root)
101
82
 
102
83
  // Skip npm's binary directory where it stores executables.
103
84
  if (dir === '.bin') {
104
85
  _log('Skipping .bin directory')
105
- return setImmediate(cb)
86
+ return
106
87
  }
107
88
 
108
89
  // Recurse into module scopes.
109
90
  if (dir[0] === '@') {
110
91
  logger.trace('Recursing into scoped module directory %s', dir)
111
- return listPackages(path.resolve(root, dir), packages, cb)
92
+ return listPackages(path.resolve(root, dir), packages)
112
93
  }
113
94
 
114
95
  // Read the package and pull out the name and version of it.
115
96
  const pkg = path.resolve(root, dir, 'package.json')
116
- fs.readFile(pkg, function onPackageRead(err, pkgFile) {
97
+ let name = null
98
+ let version = null
99
+ try {
100
+ const pkgFile = await fsPromises.readFile(pkg)
117
101
  _log('Read package at %s', pkg)
118
- if (err) {
119
- logger.debug(err, 'Could not read %s.', pkg)
120
- return cb()
121
- }
122
-
123
- let name = null
124
- let version = null
125
- try {
126
- const pkgData = JSON.parse(pkgFile)
127
- name = pkgData.name
128
- version = pkgData.version
129
- } catch (e) {
130
- logger.debug(err, 'Could not parse package file %s.', pkg)
131
- }
102
+ ;({ name, version } = JSON.parse(pkgFile))
103
+ } catch (err) {
104
+ logger.debug(err, 'Could not read %s.', pkg)
105
+ }
132
106
 
133
- packages.push([name || dir, version || '<unknown>'])
134
- _log('Package from %s added (%s@%s)', pkg, name, version)
135
- cb()
136
- })
107
+ packages.push([name || dir, version || '<unknown>'])
108
+ _log('Package from %s added (%s@%s)', pkg, name, version)
137
109
  }
138
110
  }
139
111
 
@@ -143,131 +115,73 @@ function listPackages(root, packages, callback) {
143
115
  * @param {string} root - Path to start listing dependencies from.
144
116
  * @param {Array} [children] - Array to append found dependencies to.
145
117
  * @param {object} [visited] - Map of visited directories.
146
- * @param {function} callback - Callback to send deps to.
147
- *
148
- * @return {Array} List of dependencies.
149
118
  */
150
- function listDependencies(root, children, visited, callback) {
151
- // listDependencies(root, callback)
152
- if (typeof children === 'function') {
153
- callback = children
154
- children = []
155
- visited = Object.create(null)
156
- }
157
- // listDependencies(root, {children|visited}, callback)
158
- if (typeof visited === 'function') {
159
- callback = visited
160
- if (Array.isArray(children)) {
161
- visited = Object.create(null)
162
- } else {
163
- visited = children
164
- children = []
165
- }
166
- }
119
+ async function listDependencies(root, children = [], visited = Object.create(null)) {
167
120
  _log('Listing dependencies in %s', root)
168
121
 
169
- a.waterfall(
170
- [
171
- a.apply(fs.readdir, root),
172
- function iterateDirs(dirs, cb) {
173
- a.eachLimit(dirs, 2, forEachEntry, cb)
174
- }
175
- ],
176
- function onAllDirsRead(err) {
177
- _log('Done listing dependencies in %s', root)
178
- if (err) {
179
- logger.trace(err, 'Could not read directories in %s (probably not an error)', root)
180
- return callback()
181
- }
182
- callback(null, children)
183
- }
184
- )
122
+ try {
123
+ const dirs = await fsPromises.readdir(root)
124
+ await Promise.all(dirs.map(forEachEntry))
125
+ _log('Done listing dependencies in %s', root)
126
+ } catch (err) {
127
+ logger.trace(err, 'Could not read directories in %s (probably not an error)', root)
128
+ }
185
129
 
186
- function forEachEntry(entry, cb) {
130
+ async function forEachEntry(entry) {
187
131
  _log('Checking dependencies in %s (%s)', entry, root)
188
132
 
189
133
  const candidate = path.resolve(root, entry, 'node_modules')
190
- fs.realpath(candidate, function realPathCb(err, realCandidate) {
134
+ try {
135
+ const realCandidate = await fsPromises.realpath(candidate)
191
136
  _log('Resolved %s to real path %s', candidate, realCandidate)
192
- if (err) {
193
- // Don't care to log about files that don't exist.
194
- if (err.code !== 'ENOENT') {
195
- logger.debug(err, 'Failed to resolve candidate real path %s', candidate)
196
- }
197
- _log(err, 'Real path for %s failed', candidate)
198
- return cb()
199
- }
200
-
201
137
  // Make sure we haven't been to this directory before.
202
138
  if (visited[realCandidate]) {
203
139
  logger.trace('Not revisiting %s (from %s)', realCandidate, candidate)
204
- return cb()
205
140
  }
206
141
  visited[realCandidate] = true
207
142
 
208
143
  // Load the packages and dependencies for this directory.
209
- a.series(
210
- [
211
- a.apply(listPackages, realCandidate, children),
212
- a.apply(listDependencies, realCandidate, children, visited)
213
- ],
214
- function onRecurseListComplete(loadErr) {
215
- _log('Done with dependencies in %s', realCandidate)
216
- if (loadErr) {
217
- logger.debug(loadErr, 'Failed to list dependencies in %s', realCandidate)
218
- }
219
- cb()
220
- }
221
- )
222
- })
144
+ await listPackages(realCandidate, children)
145
+ await listDependencies(realCandidate, children, visited)
146
+ _log('Done with dependencies in %s', realCandidate)
147
+ } catch (err) {
148
+ // Don't care to log about files that don't exist.
149
+ if (err.code !== 'ENOENT') {
150
+ logger.debug(err, 'Failed to resolve candidate real path %s', candidate)
151
+ }
152
+ _log(err, 'Real path for %s failed', candidate)
153
+ }
223
154
  }
224
155
  }
225
156
 
226
157
  /**
227
158
  * Build up a list of packages, starting from the current directory.
228
159
  *
229
- * @return {Object} Two lists, of packages and dependencies, with the
160
+ * @returns {object} Two lists, of packages and dependencies, with the
230
161
  * appropriate names.
231
162
  */
232
- function getLocalPackages(callback) {
163
+ async function getLocalPackages() {
233
164
  const packages = []
234
165
  const dependencies = []
235
166
  let candidate = process.cwd()
236
167
  const visited = Object.create(null)
237
168
  _log('Getting local packages')
238
169
 
239
- a.whilst(
240
- function checkCandidate(cb) {
241
- return cb(null, candidate)
242
- },
243
- function iterate(cb) {
244
- _log('Checking for local packages in %s', candidate)
245
- const root = path.resolve(candidate, 'node_modules')
246
- a.series(
247
- [
248
- a.apply(listPackages, root, packages),
249
- a.apply(listDependencies, root, dependencies, visited)
250
- ],
251
- function onListComplete(err) {
252
- _log('Done checking for local packages in %s', candidate)
253
- const last = candidate
254
- candidate = path.dirname(candidate)
255
- if (last === candidate) {
256
- candidate = null
257
- }
258
- cb(err)
259
- }
260
- )
261
- },
262
- function whileComplete(err) {
263
- _log('Done getting local packages')
264
- if (err) {
265
- callback(err)
266
- } else {
267
- callback(null, { packages: packages, dependencies: dependencies })
268
- }
170
+ while (candidate) {
171
+ _log('Checking for local packages in %s', candidate)
172
+ const root = path.resolve(candidate, 'node_modules')
173
+ await listPackages(root, packages)
174
+ await listDependencies(root, dependencies, visited)
175
+ _log('Done checking for local packages in %s', candidate)
176
+ const last = candidate
177
+ candidate = path.dirname(candidate)
178
+ if (last === candidate) {
179
+ candidate = null
269
180
  }
270
- )
181
+ }
182
+
183
+ _log('Done getting local packages')
184
+ return { packages, dependencies }
271
185
  }
272
186
 
273
187
  /**
@@ -275,48 +189,40 @@ function getLocalPackages(callback) {
275
189
  * provided root directory.
276
190
  *
277
191
  * @param {string} root - Where to start looking -- doesn't add node_modules.
278
- *
279
- * @return {Object} Two lists, of packages and dependencies, with the
192
+ * @returns {object} Two lists, of packages and dependencies, with the
280
193
  * appropriate names.
281
194
  */
282
- function getPackages(root, cb) {
195
+ async function getPackages(root) {
283
196
  const packages = []
284
197
  const dependencies = []
285
198
  _log('Getting packages from %s', root)
286
199
 
287
- a.series(
288
- [a.apply(listPackages, root, packages), a.apply(listDependencies, root, dependencies)],
289
- function onListComplete(err) {
290
- _log('Done getting packages from %s', root)
291
- if (err) {
292
- cb(err)
293
- } else {
294
- cb(null, { packages: packages, dependencies: dependencies })
295
- }
296
- }
297
- )
200
+ await listPackages(root, packages)
201
+ await listDependencies(root, dependencies)
202
+ _log('Done getting packages from %s', root)
203
+ return { packages, dependencies }
298
204
  }
299
205
 
300
206
  /**
301
207
  * Generate a list of globally-installed packages, if available / accessible
302
208
  * via the environment.
303
209
  *
304
- * @return {Object} Two lists, of packages and dependencies, with the
210
+ * @returns {object} Two lists, of packages and dependencies, with the
305
211
  * appropriate names.
306
212
  */
307
- function getGlobalPackages(cb) {
213
+ function getGlobalPackages() {
308
214
  _log('Getting global packages')
309
215
  if (process.config && process.config.variables) {
310
216
  const prefix = process.config.variables.node_prefix
311
217
  if (prefix) {
312
218
  const root = path.resolve(prefix, 'lib', 'node_modules')
313
219
  _log('Getting global packages from %s', root)
314
- return getPackages(root, cb)
220
+ return getPackages(root)
315
221
  }
316
222
  }
317
223
 
318
224
  _log('No global packages to get')
319
- setImmediate(cb, null, { packages: [], dependencies: [] })
225
+ return { packages: [], dependencies: [] }
320
226
  }
321
227
 
322
228
  /**
@@ -325,7 +231,8 @@ function getGlobalPackages(cb) {
325
231
  * package appears at most once, with all the versions joined into a
326
232
  * comma-delimited list.
327
233
  *
328
- * @return {Array.<string[]>} Sorted list of [name, version] pairs.
234
+ * @param packages
235
+ * @returns {Array.<string[]>} Sorted list of [name, version] pairs.
329
236
  */
330
237
  function flattenVersions(packages) {
331
238
  const info = Object.create(null)
@@ -383,12 +290,12 @@ function remapConfigSettings() {
383
290
  }
384
291
  }
385
292
 
386
- function getOtherPackages(callback) {
293
+ async function getOtherPackages() {
387
294
  _log('Getting other packages')
388
295
  const other = { packages: [], dependencies: [] }
389
296
 
390
297
  if (!process.env.NODE_PATH) {
391
- return callback(null, other)
298
+ return other
392
299
  }
393
300
 
394
301
  let paths
@@ -400,31 +307,25 @@ function getOtherPackages(callback) {
400
307
  }
401
308
  _log('Looking for other packages in %j', paths)
402
309
 
403
- a.eachLimit(
404
- paths,
405
- 2,
406
- function listEachOtherPackage(nodePath, cb) {
407
- if (nodePath[0] !== '/') {
408
- nodePath = path.resolve(process.cwd(), nodePath)
409
- }
410
- _log('Getting other packages from %s', nodePath)
411
- getPackages(nodePath, function onGetPackageFinish(err, nextSet) {
412
- _log('Done getting other packages from %s', nodePath)
413
- if (!err && nextSet) {
414
- other.packages.push.apply(other.packages, nextSet.packages)
415
- other.dependencies.push.apply(other.dependencies, nextSet.dependencies)
416
- }
417
- cb(err)
418
- })
419
- },
420
- function onOtherFinish(err) {
421
- _log('Done getting other packages')
422
- callback(err, other)
310
+ const pathPromises = paths.map((nodePath) => {
311
+ if (nodePath[0] !== '/') {
312
+ nodePath = path.resolve(process.cwd(), nodePath)
423
313
  }
424
- )
314
+ _log('Getting other packages from %s', nodePath)
315
+ return getPackages(nodePath)
316
+ })
317
+
318
+ const otherPackages = await Promise.all(pathPromises)
319
+ otherPackages.forEach((pkg) => {
320
+ other.packages.push.apply(other.packages, pkg.packages)
321
+ other.dependencies.push.apply(other.dependencies, pkg.dependencies)
322
+ })
323
+
324
+ _log('Done getting other packages')
325
+ return other
425
326
  }
426
327
 
427
- function getHomePackages(cb) {
328
+ async function getHomePackages() {
428
329
  let homeDir = null
429
330
  if (process.platform === 'win32') {
430
331
  if (process.env.USERDIR) {
@@ -436,20 +337,14 @@ function getHomePackages(cb) {
436
337
 
437
338
  _log('Getting home packages from %s', homeDir)
438
339
  if (!homeDir) {
439
- return cb(null, null)
340
+ return
440
341
  }
441
342
 
442
- a.mapSeries(
443
- {
444
- home: path.resolve(homeDir, '.node_modules'),
445
- homeOld: path.resolve(homeDir, '.node_libraries')
446
- },
447
- getPackages,
448
- function onHomeFinish(err, packages) {
449
- _log('Done getting home packages from %s', homeDir)
450
- cb(err, packages)
451
- }
452
- )
343
+ const homePath = path.resolve(homeDir, '.node_modules')
344
+ const homeOldPath = path.resolve(homeDir, '.node_libraries')
345
+ const home = await getPackages(homePath)
346
+ const homeOld = await getPackages(homeOldPath)
347
+ return { home, homeOld }
453
348
  }
454
349
 
455
350
  /**
@@ -461,59 +356,47 @@ function getHomePackages(cb) {
461
356
  * This function works entirely via side effects using the addSetting
462
357
  * function.
463
358
  */
464
- function findPackages(cb) {
359
+ async function findPackages() {
465
360
  _log('Finding all packages')
466
- a.parallelLimit(
467
- {
468
- local: time(getLocalPackages),
469
- global: time(getGlobalPackages),
470
- other: time(getOtherPackages),
471
- home: time(getHomePackages)
472
- },
473
- 2,
474
- function onPackageComplete(err, data) {
475
- _log('Done finding all packages')
476
- if (err) {
477
- return cb(err)
478
- }
479
-
480
- const packages = data.local.packages
481
- packages.push.apply(packages, data.global.packages)
482
- packages.push.apply(packages, data.other.packages)
483
-
484
- const dependencies = data.local.dependencies
485
- dependencies.push.apply(dependencies, data.global.dependencies)
486
- dependencies.push.apply(dependencies, data.other.dependencies)
487
-
488
- if (data.home) {
489
- if (data.home.home) {
490
- packages.unshift.apply(packages, data.home.home.packages)
491
- dependencies.unshift.apply(dependencies, data.home.home.dependencies)
492
- }
493
- if (data.home.homeOld) {
494
- packages.unshift.apply(packages, data.home.homeOld.packages)
495
- dependencies.unshift.apply(dependencies, data.home.homeOld.dependencies)
496
- }
497
- }
498
-
499
- addSetting('Packages', flattenVersions(packages))
500
- addSetting('Dependencies', flattenVersions(dependencies))
501
- cb()
361
+ const pkgPromises = [
362
+ time(getLocalPackages),
363
+ time(getGlobalPackages),
364
+ time(getOtherPackages),
365
+ time(getHomePackages)
366
+ ]
367
+ const [local, global, other, home] = await Promise.all(pkgPromises)
368
+ _log('Done finding all packages')
369
+ const packages = local.packages
370
+ packages.push.apply(packages, global.packages)
371
+ packages.push.apply(packages, other.packages)
372
+
373
+ const dependencies = local.dependencies
374
+ dependencies.push.apply(dependencies, global.dependencies)
375
+ dependencies.push.apply(dependencies, other.dependencies)
376
+
377
+ if (home) {
378
+ if (home.home) {
379
+ packages.unshift.apply(packages, home.home.packages)
380
+ dependencies.unshift.apply(dependencies, home.home.dependencies)
381
+ }
382
+ if (home.homeOld) {
383
+ packages.unshift.apply(packages, home.homeOld.packages)
384
+ dependencies.unshift.apply(dependencies, home.homeOld.dependencies)
502
385
  }
503
- )
386
+ }
387
+
388
+ addSetting('Packages', flattenVersions(packages))
389
+ addSetting('Dependencies', flattenVersions(dependencies))
504
390
  }
505
391
 
506
- function time(fn) {
392
+ async function time(fn) {
507
393
  const name = fn.name
508
- return function timeWrapper(cb) {
509
- const start = Date.now()
510
- logger.trace('Starting %s', name)
511
- return fn(function wrappedCb() {
512
- const end = Date.now()
513
- logger.trace('Finished %s in %dms', name, end - start)
514
- cb.apply(this, arguments)
515
- })
516
- }
394
+ const start = Date.now()
395
+ logger.trace('Starting %s', name)
396
+ const data = await fn()
397
+ const end = Date.now()
398
+ logger.trace('Finished %s in %dms', name, end - start)
399
+ return data
517
400
  }
518
401
 
519
402
  /**
@@ -565,7 +448,7 @@ function refreshSyncOnly() {
565
448
  /**
566
449
  * Reset settings and gather them, built to minimally refactor this file.
567
450
  */
568
- function refresh(cb) {
451
+ async function refresh() {
569
452
  _log('Refreshing environment settings')
570
453
  refreshSyncOnly()
571
454
 
@@ -576,38 +459,34 @@ function refresh(cb) {
576
459
  settings.Packages = packages
577
460
  settings.Dependencies = dependencies
578
461
  _log('Using cached values')
579
- setImmediate(cb)
580
- } else {
581
- _log('Fetching new package information')
582
- findPackages(cb)
462
+ return
583
463
  }
464
+ _log('Fetching new package information')
465
+ await findPackages()
584
466
  }
585
467
 
586
468
  /**
587
469
  * Refreshes settings and returns the settings object.
588
470
  *
589
471
  * @private
590
- *
591
- * @param {function} cb - Callback to send results to.
472
+ * @returns {Promise}
592
473
  */
593
- function getJSON(cb) {
474
+ async function getJSON() {
594
475
  _log('Getting environment JSON')
595
- refresh(function onRefreshFinish(err) {
596
- _log('Environment refresh finished')
597
- if (err) {
598
- cb(err)
599
- return
600
- }
476
+ try {
477
+ await refresh()
478
+ } catch (err) {
479
+ // swallow error
480
+ }
601
481
 
602
- const items = []
603
- Object.keys(settings).forEach(function settingKeysForEach(key) {
604
- settings[key].forEach(function settingsValuesForEach(setting) {
605
- items.push([key, setting])
606
- })
482
+ const items = []
483
+ Object.keys(settings).forEach(function settingKeysForEach(key) {
484
+ settings[key].forEach(function settingsValuesForEach(setting) {
485
+ items.push([key, setting])
607
486
  })
608
- _log('JSON got')
609
- cb(null, items)
610
487
  })
488
+ _log('JSON got')
489
+ return items
611
490
  }
612
491
 
613
492
  // At startup, do the synchronous environment scanning stuff.
@@ -643,10 +522,10 @@ module.exports = {
643
522
  clearSetting('Dispatcher')
644
523
  clearSetting('Dispatcher Version')
645
524
  },
646
- listPackages: listPackages,
647
- getJSON: getJSON,
525
+ listPackages,
526
+ getJSON,
648
527
  get: getSetting,
649
- refresh: refresh
528
+ refresh
650
529
  }
651
530
 
652
531
  /**
@@ -78,9 +78,7 @@ function wrapStart(shim, original) {
78
78
  segment.addAttribute('grpc.statusCode', code)
79
79
  segment.addAttribute('grpc.statusText', details)
80
80
 
81
- // Java captures client errors based on status code
82
- // but has specific gRPC configuration to turn off
83
- if (code !== 0) {
81
+ if (code !== 0 && shim.agent.config.grpc.record_errors) {
84
82
  // this is currently just creating an error from the details string
85
83
  shim.agent.errors.add(segment.transaction, details)
86
84
  }
@@ -273,7 +273,8 @@ const LOGGING = {
273
273
  WARN: `${LOGGING_LINES_PREFIX}/WARN`,
274
274
  ERROR: `${LOGGING_LINES_PREFIX}/ERROR`,
275
275
  DEBUG: `${LOGGING_LINES_PREFIX}/DEBUG`,
276
- TRACE: `${LOGGING_LINES_PREFIX}/TRACE`
276
+ TRACE: `${LOGGING_LINES_PREFIX}/TRACE`,
277
+ UNKNOWN: `${LOGGING_LINES_PREFIX}/UNKNOWN`
277
278
  },
278
279
  LIBS: {
279
280
  PINO: `${SUPPORTABILITY.LOGGING}/${NODEJS.PREFIX}pino/enabled`,