newrelic 4.6.0 → 4.9.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.
Files changed (44) hide show
  1. package/NEWS.md +222 -1
  2. package/api.js +24 -11
  3. package/bin/compare-bench-results.js +167 -0
  4. package/bin/run-bench.js +87 -44
  5. package/bin/travis-setup.sh +18 -7
  6. package/index.js +16 -8
  7. package/lib/collector/remote-method.js +12 -0
  8. package/lib/config/default.js +5 -0
  9. package/lib/config/env.js +2 -1
  10. package/lib/config/index.js +5 -0
  11. package/lib/db/tracer.js +17 -6
  12. package/lib/environment.js +1 -1
  13. package/lib/errors/index.js +1 -1
  14. package/lib/instrumentation/bluebird.js +35 -45
  15. package/lib/instrumentation/core/async_hooks.js +8 -8
  16. package/lib/instrumentation/core/child_process.js +41 -34
  17. package/lib/instrumentation/core/crypto.js +9 -14
  18. package/lib/instrumentation/core/dns.js +9 -13
  19. package/lib/instrumentation/core/domain.js +10 -12
  20. package/lib/instrumentation/core/fs.js +47 -38
  21. package/lib/instrumentation/core/globals.js +12 -17
  22. package/lib/instrumentation/core/http.js +3 -3
  23. package/lib/instrumentation/core/inspector.js +8 -7
  24. package/lib/instrumentation/core/net.js +62 -66
  25. package/lib/instrumentation/core/timers.js +79 -40
  26. package/lib/instrumentation/core/zlib.js +22 -8
  27. package/lib/instrumentation/mongodb.js +158 -115
  28. package/lib/instrumentations.js +3 -2
  29. package/lib/priority-queue.js +5 -2
  30. package/lib/shim/constants.js +6 -0
  31. package/lib/shim/datastore-shim.js +1 -1
  32. package/lib/shim/index.js +9 -5
  33. package/lib/shim/message-shim.js +5 -4
  34. package/lib/shim/promise-shim.js +563 -0
  35. package/lib/shim/shim.js +90 -11
  36. package/lib/shim/specs/index.js +8 -5
  37. package/lib/shimmer.js +70 -28
  38. package/lib/transaction/dt-payload.js +16 -0
  39. package/lib/transaction/handle.js +1 -1
  40. package/lib/transaction/index.js +22 -8
  41. package/lib/transaction/trace/aggregator.js +3 -3
  42. package/lib/transaction/trace/index.js +30 -37
  43. package/lib/util/codec.js +4 -1
  44. package/package.json +10 -4
package/NEWS.md CHANGED
@@ -1,3 +1,150 @@
1
+ ### 4.9.0 (2018-10-01):
2
+
3
+ * Updated DT payload creation to use `primary_application_id` from connect response.
4
+
5
+ * Added protection against functions with modified prototypes in `shim.applySegment`.
6
+
7
+ * Replaced SQL ID hash generation algorithm with SHA1 instead of MD5 to allow usage
8
+ in FIPS compliant environments.
9
+
10
+ * Leveraged 16 hex digits for creation of SQL ID.
11
+
12
+ * Fixed `codec.decode()` callback bug that would re-call a callback with an error
13
+ thrown within the callback.
14
+
15
+ * Added `superagent` as built-in instrumentation.
16
+
17
+ This instrumentation just maintains transaction state when using the `superagent`
18
+ module to make HTTP requests with either callbacks or promises.
19
+
20
+ * Updated `noticeError` API method to be partially functional in High Security Mode.
21
+
22
+ In HSM, any custom attributes will be ignored, but the error will still be tracked.
23
+ This brings the Node agent in line with the behavior of other language agents.
24
+
25
+ * Upgraded ejs module to get rid of Github security warnings. The ejs module was
26
+ only used for tests and not in main agent code.
27
+
28
+ * Fixed bug requiring Cross Application Tracing (CAT) to be enabled for Distributed
29
+ Tracing (DT) `createDistributedTracePayload` and `acceptDistributedTracePayload`
30
+ APIs to function. DT configuration will no longer consider CAT configuration.
31
+
32
+ * Changes DT payload configuration log messages to debug level as it is not uncommon
33
+ for calls to occur before server configuration has been retrieved.
34
+
35
+ * Converted `net` instrumentation to use shim api.
36
+
37
+ * Converted child_process instrumentation to newer shim style.
38
+
39
+ * Converted Timers instrumentation to newer shim style.
40
+
41
+ * Fixed bug in wrap() that would fail to wrap callbacks if the callback index was 0.
42
+
43
+ * Added `PromiseShim` class for instrumenting promise libraries.
44
+
45
+ * Support for setting `transaction_tracer.transaction_threshold` to 0 has been added.
46
+
47
+ * The agent now respects `NEW_RELIC_TRACER_THRESHOLD`.
48
+
49
+ Previously, this environment variable was stored as a string. The environment
50
+ variable is now stored as a float.
51
+
52
+ * Converted zlib instrumentation to use shim API.
53
+
54
+ ### 4.8.1 (2018-08-27):
55
+
56
+ * Converted File System instrumentation to use newer shim style.
57
+
58
+ * Agent instrumentation will no longer interfere with promisification of core
59
+ methods.
60
+
61
+ Some core methods expose pre-promisified versions of the methods as a reference
62
+ on the method itself. When instrumenting these methods, it neglected to forward
63
+ these references onto the wrapper function. Now the instrumentation will properly
64
+ forward property look ups to the original method.
65
+
66
+ * Converted DNS instrumentation to newer shim style.
67
+
68
+ * Added tracking of callbacks to DNS instrumentation.
69
+
70
+ * Converted crypto instrumentation to newer shim style.
71
+
72
+ * Updated domains instrumentation to use an instrumentation shim.
73
+
74
+ * Refactored the global instrumentation to use the shim API.
75
+
76
+ * Ported inspector instrumentation to use an instrumentation shim.
77
+
78
+ * Ported async_hooks based promise instrumentation over to using shims.
79
+
80
+ * Added shim types for core instrumentations.
81
+
82
+ * Fixed outbound https call to use example.com to resolve integration test issue.
83
+
84
+ * Fixed tests for ioredis 4.0.0 and above.
85
+
86
+ * Improved benchmark comparison output.
87
+
88
+ * Added `http` benchmark tests.
89
+
90
+ ### 4.8.0 (2018-08-13):
91
+
92
+ * Added JSON-formatted output to benchmarks to enable automated benchmark comparison.
93
+
94
+ * Updated the benchmark runner to measure specifically userland CPU overhead.
95
+
96
+ * Added DatastoreShim benchmarks.
97
+
98
+ * Fixed MongoDB instrumentation for driver versions greater than 3.0.6.
99
+
100
+ Mongo 3.0.6 removed metadata the Agent relied upon to instrument the driver. This
101
+ fixes that by going back to the old method of manually listing all objects and
102
+ methods to instrument.
103
+
104
+ * Implemented enforcement of `max_payload_size_in_bytes` config value.
105
+
106
+ Any payload during the harvest sequence that exceeds the configured limit will
107
+ be discarded.
108
+
109
+ * Updated MySQL versioned tests to run against the latest release.
110
+
111
+ ### 4.7.0 (2018-07-31):
112
+
113
+ * Added support for distributed tracing.
114
+
115
+ Distributed tracing lets you see the path that a request takes as it travels
116
+ through your distributed system. By showing the distributed activity through a
117
+ unified view, you can troubleshoot and understand a complex system better than
118
+ ever before.
119
+
120
+ Distributed tracing is available with an APM Pro or equivalent subscription.
121
+ To see a complete distributed trace, you need to enable the feature on a set of
122
+ neighboring services. Enabling distributed tracing changes the behavior of some
123
+ New Relic features, so carefully consult the [transition guide](https://docs.newrelic.com/docs/transition-guide-distributed-tracing) before
124
+ you enable this feature.
125
+
126
+ To enable distributed tracing, set `distributed_tracing.enabled` to `true` in
127
+ your `newrelic.js` file, or set `NEW_RELIC_DISTRIBUTED_TRACING_ENABLED` in your
128
+ environment.
129
+
130
+ * Added a warning for too-new versions of Node.js during agent startup.
131
+
132
+ * Appropriately obfuscated SQL statements will now be included in all transaction
133
+ traces.
134
+
135
+ Previously, the agent would only include the SQL statements if the corresponding
136
+ query was sufficiently slow.
137
+
138
+ * Added ability to execute instrumentation functions in the context of the segment
139
+ the segment descriptor is describing.
140
+
141
+ All `record*` methods supplied by all instrumentation shim classes now allow for
142
+ a function to be executed under the context of the segment the record call will
143
+ produce. This may be done by supplying a function in the `inContext` key for the
144
+ segment descriptor passed to the record method.
145
+
146
+ * Reservoirs will now respect setting their size to 0.
147
+
1
148
  ### 4.6.0 (2018-07-24):
2
149
 
3
150
  * Added full support for Node v10.
@@ -11,6 +158,8 @@
11
158
  * Updated tests to use `asyncResource.runInAsyncScope` instead of `emitBefore` and
12
159
  `emitAfter`
13
160
 
161
+ * Pulled `distributed_tracing` config value from behind `feature_flag`.
162
+
14
163
  ### 4.5.1 (2018-07-18):
15
164
 
16
165
  - The agent will now properly remerge event data on collection failure.
@@ -33,6 +182,12 @@
33
182
 
34
183
  * Updated Hapi v17 instrumentation to wrap `server` export, in addition to `Server`.
35
184
 
185
+ * `ROOT` segment no longer turns into a span event.
186
+
187
+ * Fixed span collection when transactions are `sampled=false`.
188
+
189
+ * Removed `grandparentId` from spans.
190
+
36
191
  ### 4.4.0 (2018-07-12):
37
192
 
38
193
  * Added config `utilization` env vars to the `BOOLEAN_VARS` set.
@@ -44,6 +199,29 @@
44
199
 
45
200
  * Added node v10 to the test matrix.
46
201
 
202
+ * Converted distributed trace `x-newrelic-trace` header name to `newrelic`.
203
+
204
+ * Added support for different transport types in distributed tracing.
205
+
206
+ * Added more tests around priority/sampled attributes on traces and events.
207
+
208
+ * Lazily calculate transaction priority only when needed.
209
+
210
+ * Transaction priority is now truncated to 6 decimal places on generation.
211
+
212
+ * Adaptive sampling now uses the `sampling_target` and
213
+ `sampling_target_period_in_seconds` configuration values.
214
+
215
+ With these configurations, the adaptive sampling window is separated from the
216
+ harvest window.
217
+
218
+ * Removed `nr.tripId` attribute from distributed trace intrinsics.
219
+
220
+ * Default span events to enabled.
221
+
222
+ These are still protected behind `feature_flag.distributed_tracing` which defaults
223
+ to `false`.
224
+
47
225
  ### 4.3.0 (2018-07-09):
48
226
 
49
227
  * Added `nonce` option for `newrelic.getBrowserTimingHeader()`
@@ -65,7 +243,7 @@
65
243
 
66
244
  * Fixed issue with tracking external requests to default ports.
67
245
 
68
- Special thanks to Ryan King for pinpointing the cause of this issue.
246
+ Special thanks to Ryan King for pinpointing the cause of this issue.
69
247
 
70
248
  * Added extra check for handling arrays of functions when wrapping middleware
71
249
  mounters.
@@ -103,6 +281,25 @@
103
281
 
104
282
  * No longer download gcc on test suites that do not require it.
105
283
 
284
+ * Added `url` parameter to `http` external segments.
285
+
286
+ * Renamed request parameters on external segments.
287
+
288
+ Previously these were named just the parameter name (e.g. `/foo?bar=baz` would
289
+ become the parameter `"bar": "baz"`). Now they are prefixed with
290
+ `request.parameter`. (e.g. `"request.parameter.bar": "baz"`).
291
+
292
+ * Added `EventAggregator` base class.
293
+
294
+ The `ErrorAggregator` class was refactored and most generic event aggregation
295
+ logic was moved to the new `EventAggregator` class.
296
+
297
+ * Added `SpanEvent` and `SpanAggregator` classes.
298
+
299
+ * Added Span event generation to the trace `end` method.
300
+
301
+ * Added Span events to harvest cycle steps.
302
+
106
303
  ### 4.1.5 (2018-06-11):
107
304
 
108
305
  * Make `require()` statements explicitly reference `package.json` as a `.json` file.
@@ -145,6 +342,11 @@
145
342
  result in a false `uninstrumented` status, because the agent would interpret
146
343
  `redis.js` as the module itself.
147
344
 
345
+ * Moved `computeSampled` call to `Transaction` constructor.
346
+
347
+ Previously it was only called in `createDistributedTracePayload`, but this
348
+ gives all transactions a `sampled` value, and potentially a boosted priority.
349
+
148
350
  ### 4.1.4 (2018-06-04):
149
351
 
150
352
  * Transaction stubs are now created properly in `api#getTransaction`
@@ -168,6 +370,25 @@
168
370
 
169
371
  * Modularlized configuration constants to improve readability.
170
372
 
373
+ * Added `distributed_tracing` feature flag.
374
+
375
+ * Added `acceptDistributedTracePayload` method to `Transaction`.
376
+
377
+ * Added `createDistributedTracePayload` method to `Transaction`.
378
+
379
+ * Updated `Agent#recordSupportability` to not include `Nodejs/` in the default metric name.
380
+
381
+ * Added distributed tracing methods to `TransactionHandle`.
382
+
383
+ * Added distributed tracing cases for `http` and `other` metric recorders.
384
+
385
+ * Implemented `_addDistributedTraceInstrinsics` on `Transaction`.
386
+
387
+ If the `distributed_tracing` feature flag is enabled, the agent will ignore old
388
+ CAT attributes in favor of distributed trace–related ones.
389
+
390
+ * Added integration tests around better CAT functionality.
391
+
171
392
  ### 4.1.2 (2018-05-22):
172
393
 
173
394
  * Fixed access to properties on promisified methods.
package/api.js CHANGED
@@ -397,29 +397,35 @@ API.prototype.setIgnoreTransaction = function setIgnoreTransaction(ignored) {
397
397
  * Optional. Any custom attributes to be displayed in the New Relic UI.
398
398
  */
399
399
  API.prototype.noticeError = function noticeError(error, customAttributes) {
400
- var metric = this.agent.metrics.getOrCreateMetric(
400
+ const metric = this.agent.metrics.getOrCreateMetric(
401
401
  NAMES.SUPPORTABILITY.API + '/noticeError'
402
402
  )
403
403
  metric.incrementCallCount()
404
404
 
405
- // If high security mode is on, noticeError is disabled.
406
- if (this.agent.config.high_security === true) {
407
- logger.warnOnce(
408
- 'Notice Error',
409
- 'Notice error API is disabled by high security mode.'
410
- )
411
- return false
412
- } else if (!this.agent.config.api.notice_error_enabled) {
405
+ if (!this.agent.config.api.notice_error_enabled) {
413
406
  logger.debug(
414
407
  'Config.api.notice_error_enabled set to false, not collecting error'
415
408
  )
416
409
  return false
417
410
  }
418
411
 
412
+ // If high security mode is on or custom attributes are disabled,
413
+ // noticeError does not collect custom attributes.
414
+ if (this.agent.config.high_security === true) {
415
+ logger.debug(
416
+ 'Passing custom attributes to notice error API is disabled in high security mode.'
417
+ )
418
+ } else if (!this.agent.config.api.custom_attributes_enabled) {
419
+ logger.debug(
420
+ 'Config.api.custom_attributes_enabled set to false, ' +
421
+ 'ignoring custom error attributes.'
422
+ )
423
+ }
424
+
419
425
  if (typeof error === 'string') {
420
426
  error = new Error(error)
421
427
  }
422
- var transaction = this.agent.tracer.getTransaction()
428
+ const transaction = this.agent.tracer.getTransaction()
423
429
 
424
430
  this.agent.errors.addUserError(transaction, error, customAttributes)
425
431
  }
@@ -702,6 +708,13 @@ function createTracer(name, callback) {
702
708
  return arity.fixArity(callback, tracer.bindFunction(callback, segment, true))
703
709
  }
704
710
 
711
+ /**
712
+ * @callback startSegmentCallback
713
+ * @param {function} cb
714
+ * The function to time with the created segment.
715
+ * @return {Promise=} Returns a promise if cb returns a promise.
716
+ */
717
+
705
718
  /**
706
719
  * Wraps the given handler in a segment which may optionally be turned into a
707
720
  * metric.
@@ -720,7 +733,7 @@ function createTracer(name, callback) {
720
733
  * up on the transaction breakdown table and server breakdown graph. Segments
721
734
  * just show up in transaction traces.
722
735
  *
723
- * @param {function(cb) -> ?Promise} handler
736
+ * @param {startSegmentCallback} handler
724
737
  * The function to track as a segment.
725
738
  *
726
739
  * @param {function} [callback]
@@ -0,0 +1,167 @@
1
+ 'use strict'
2
+ /* eslint-disable no-console */
3
+
4
+ const async = require('async')
5
+ const fs = require('fs')
6
+
7
+ if (process.argv.length !== 4) {
8
+ console.log('Usage: %s %s <baseline> <upstream>', process.argv[0], process.argv[1])
9
+ console.log(' <baseline> JSON file containing benchmark results for upstream')
10
+ console.log(' upstream comparison.')
11
+ console.log(' <downstream> JSON file containing benchmark results from')
12
+ console.log(' downstream branch to compare against base.')
13
+ process.exit(1)
14
+ }
15
+
16
+ async.map(process.argv.slice(2), (file, cb) => {
17
+ fs.readFile(file, {encoding: 'utf8'}, (err, data) => {
18
+ if (err) {
19
+ return cb(err)
20
+ }
21
+
22
+ let parsed = null
23
+ try {
24
+ parsed = JSON.parse(data)
25
+ } catch (parseError) {
26
+ return cb(parseError)
27
+ }
28
+
29
+ cb(null, parsed)
30
+ })
31
+ }, (err, resultFiles) => {
32
+ if (err) {
33
+ console.log('Failed to load files.')
34
+ console.log(err)
35
+ process.exit(2)
36
+ }
37
+
38
+ const baseline = resultFiles[0]
39
+ const downstream = resultFiles[1]
40
+
41
+ const baselineFiles = Object.keys(baseline)
42
+ const downstreamFiles = Object.keys(downstream)
43
+ const warnings = []
44
+
45
+ diffArrays(baselineFiles, downstreamFiles).forEach((file) => {
46
+ warnings.push(`- **WARNING**: File "${file}" in base but not branch.`)
47
+ })
48
+ diffArrays(downstreamFiles, baselineFiles).forEach((file) => {
49
+ warnings.push(`- **NOTE**: File "${file}" in branch but not base.`)
50
+ })
51
+
52
+ let allPassing = true
53
+ const details = baselineFiles.sort().map((testFile) => {
54
+ const base = baseline[testFile]
55
+ const down = downstream[testFile]
56
+
57
+ if (!down) {
58
+ return [
59
+ '<details>',
60
+ `<summary>${testFile} file missing from branch</summary>`,
61
+ '',
62
+ '</details>'
63
+ ].join('\n')
64
+ }
65
+
66
+ let filePassing = true
67
+ const baseTests = Object.keys(base)
68
+ const downTests = Object.keys(down)
69
+
70
+ diffArrays(baseTests, downTests).forEach((test) => {
71
+ warnings.push(`- **WARNING**: Test "${test}" in base but not branch.`)
72
+ })
73
+ diffArrays(downTests, baseTests).forEach((test) => {
74
+ warnings.push(`- **NOTE**: Test "${test}" in branch but not base.`)
75
+ })
76
+
77
+ const results = baseTests.sort().map((test) => {
78
+ const passes = compareResults(base[test], down[test])
79
+ filePassing = filePassing && passes
80
+
81
+ return [
82
+ '<details>',
83
+ `<summary>${test}: ${passMark(passes)}</summary>`,
84
+ '',
85
+ formatResults(base[test], down[test]),
86
+ '</details>',
87
+ ''
88
+ ].join('\n')
89
+ }).join('\n')
90
+ allPassing = allPassing && filePassing
91
+
92
+ return [
93
+ '<details>',
94
+ `<summary>${testFile}: ${passMark(filePassing)}</summary>`,
95
+ '',
96
+ results,
97
+ '',
98
+ '-----------------------------------------------------------------------',
99
+ '</details>'
100
+ ].join('\n')
101
+ }).join('\n\n')
102
+
103
+ if (warnings.length) {
104
+ console.log('### WARNINGS')
105
+ console.log(warnings.join('\n'))
106
+ console.log('')
107
+ }
108
+
109
+ console.log(`### Benchmark Results: ${passMark(allPassing)}`)
110
+ console.log('')
111
+ console.log('### Details')
112
+ console.log('_Lower is better._')
113
+ console.log(details)
114
+
115
+ if (!allPassing) {
116
+ process.exitCode = -1
117
+ }
118
+ })
119
+
120
+ function diffArrays(a, b) {
121
+ return a.filter((elem) => !b.includes(elem))
122
+ }
123
+
124
+ function compareResults(base, down) {
125
+ const delta = down.mean - base.mean
126
+ const deltaPercent = delta / base.mean
127
+ if (Math.abs(delta) < 0.1) {
128
+ return deltaPercent < 100
129
+ }
130
+ return deltaPercent < 2
131
+ }
132
+
133
+ function passMark(passes) {
134
+ return passes ? '✔' : '✘'
135
+ }
136
+
137
+ function formatResults(base, down) {
138
+ return [
139
+ 'Field | Upstream (ms) | Downstream (ms) | Delta (ms) | Delta (%)',
140
+ '----- | ------------: | --------------: | ---------: | --------:',
141
+ formatField('numSamples'),
142
+ formatField('mean'),
143
+ formatField('stdDev'),
144
+ formatField('max'),
145
+ formatField('min'),
146
+ formatField('5thPercentile'),
147
+ formatField('95thPercentile'),
148
+ formatField('median')
149
+ ].join('\n')
150
+
151
+ function formatField(field) {
152
+ const baseValue = base[field]
153
+ const downValue = down[field]
154
+ const diffValue = downValue - baseValue
155
+ const diffPercent = (100 * diffValue / baseValue).toFixed(2)
156
+ const prefix = diffValue >= 0 ? '+' : ''
157
+
158
+ return (
159
+ `${field} | ${fixValue(baseValue)} | ${fixValue(downValue)} |` +
160
+ ` ${fixValue(diffValue)} | ${prefix}${diffPercent}%`
161
+ )
162
+ }
163
+
164
+ function fixValue(value) {
165
+ return value % 1 ? value.toFixed(5) : value
166
+ }
167
+ }
package/bin/run-bench.js CHANGED
@@ -36,54 +36,97 @@ if (tests.length === 0 && globs.length === 0) {
36
36
  )
37
37
  }
38
38
 
39
- a.series([
40
- function resolveGlobs(cb) {
41
- if (!globs.length) {
42
- return cb()
43
- }
39
+ class ConsolePrinter {
40
+ /* eslint-disable no-console */
41
+ addTest(name, child) {
42
+ console.log(name)
43
+ child.stdout.on('data', (d) => process.stdout.write(d))
44
+ child.stderr.on('data', (d) => process.stderr.write(d))
45
+ child.once('exit', () => console.log(''))
46
+ }
47
+
48
+ finish() {
49
+ console.log('')
50
+ }
51
+ /* eslint-enable no-console */
52
+ }
53
+
54
+ class JSONPrinter {
55
+ constructor() {
56
+ this._tests = Object.create(null)
57
+ }
58
+
59
+ addTest(name, child) {
60
+ let output = ''
61
+ this._tests[name] = null
62
+ child.stdout.on('data', (d) => output += d.toString())
63
+ child.stdout.on('end', () => this._tests[name] = JSON.parse(output))
64
+ child.stderr.on('data', (d) => process.stderr.write(d))
65
+ }
66
+
67
+ finish() {
68
+ /* eslint-disable no-console */
69
+ console.log(JSON.stringify(this._tests, null, 2))
70
+ /* eslint-enable no-console */
71
+ }
72
+ }
73
+
74
+ run()
75
+
76
+ function run() {
77
+ const printer = opts.json ? new JSONPrinter() : new ConsolePrinter()
44
78
 
45
- a.map(globs, glob, function afterGlobbing(err, resolved) {
46
- if (err) {
47
- console.error('Failed to glob:', err)
48
- process.exitCode = -1
49
- return cb(err)
79
+ a.series([
80
+ function resolveGlobs(cb) {
81
+ if (!globs.length) {
82
+ return cb()
50
83
  }
51
- resolved.forEach(function mergeResolved(files) {
52
- files.forEach(function mergeFile(file) {
53
- if (tests.indexOf(file) === -1) {
54
- tests.push(file)
55
- }
84
+
85
+ a.map(globs, glob, function afterGlobbing(err, resolved) {
86
+ if (err) {
87
+ console.error('Failed to glob:', err)
88
+ process.exitCode = -1
89
+ return cb(err)
90
+ }
91
+ resolved.forEach(function mergeResolved(files) {
92
+ files.forEach(function mergeFile(file) {
93
+ if (tests.indexOf(file) === -1) {
94
+ tests.push(file)
95
+ }
96
+ })
56
97
  })
98
+ cb()
57
99
  })
58
- cb()
59
- })
60
- },
61
- function runBenchmarks(cb) {
62
- tests.sort()
63
- a.eachSeries(tests, function spawnEachFile(file, cb) {
64
- var test = path.relative(benchpath, file)
65
-
66
- console.log(test)
67
- var args = ['--expose-gc', file]
68
- if (opts.inspect) {
69
- args.unshift('--inspect-brk')
70
- }
71
- var child = cp.spawn('node', args, {cwd: cwd, stdio: 'inherit'})
72
- child.on('error', cb)
73
- child.on('exit', function onChildExit(code) {
74
- console.log('')
75
- if (code) {
76
- return cb(new Error('Benchmark exited with code ' + code))
100
+ },
101
+ function runBenchmarks(cb) {
102
+ tests.sort()
103
+ a.eachSeries(tests, function spawnEachFile(file, cb) {
104
+ var test = path.relative(benchpath, file)
105
+
106
+ var args = [file]
107
+ if (opts.inspect) {
108
+ args.unshift('--inspect-brk')
109
+ }
110
+ var child = cp.spawn('node', args, {cwd: cwd, stdio: 'pipe'})
111
+ printer.addTest(test, child)
112
+
113
+ child.on('error', cb)
114
+ child.on('exit', function onChildExit(code) {
115
+ if (code) {
116
+ return cb(new Error('Benchmark exited with code ' + code))
117
+ }
118
+ cb()
119
+ })
120
+ }, function afterSpawnEachFile(err) {
121
+ if (err) {
122
+ console.error('Spawning failed:', err)
123
+ process.exitCode = -2
124
+ return cb(err)
77
125
  }
78
126
  cb()
79
127
  })
80
- }, function afterSpawnEachFile(err) {
81
- if (err) {
82
- console.error('Spawning failed:', err)
83
- process.exitCode = -2
84
- return cb(err)
85
- }
86
- cb()
87
- })
88
- }
89
- ])
128
+ }
129
+ ], () => {
130
+ printer.finish()
131
+ })
132
+ }
@@ -1,9 +1,10 @@
1
1
  #! /bin/bash
2
2
 
3
- function get_gcc_version {
4
- local gcc_version_match='[[:digit:]]\.[[:digit:]]\.[[:digit:]]'
5
- local gcc_version=`$CC --version 2>/dev/null | grep -o "$gcc_version_match" | head -1`
6
- echo $gcc_version | grep -o '[[:digit:]]' | head -1
3
+
4
+ function get_version {
5
+ local num='[[:digit:]][[:digit:]]*' # Grep doesn't have `+` operator.
6
+ local version=`$1 --version 2>/dev/null | grep -o "$num\.$num\.$num" | head -1`
7
+ echo $version | grep -o "$num" | head -1
7
8
  }
8
9
 
9
10
  TOOLCHAIN_ADDED="false"
@@ -15,15 +16,25 @@ function add_toolchain {
15
16
  TOOLCHAIN_ADDED="true"
16
17
  }
17
18
 
18
- # Only upgrade GCC if we need to.
19
19
 
20
20
  if [ "$SUITE" = "versioned" ]; then
21
- if [ "$(get_gcc_version)" != "5" ]; then
21
+
22
+ # GCC 5 is the lowest version of GCC we can use.
23
+ if [ "$(get_version gcc)" == "4" ]; then
22
24
  echo " --- upgrading GCC --- "
23
25
  add_toolchain
24
26
  ./bin/travis-install-gcc5.sh > /dev/null
25
27
  else
26
- echo " --- not upgrading GCC --- "
28
+ echo " --- not upgrading GCC ($(gcc --version)) --- "
29
+ fi
30
+
31
+ # npm 2 has an issue installing correctly for the superagent versioned tests.
32
+ # TODO: Remove this check when deprecating Node <5.
33
+ if [ "$(get_version npm)" == "2" ]; then
34
+ echo " -- upgrading npm --- "
35
+ npm install -g npm@3
36
+ else
37
+ echo " --- not upgrading npm ($(npm --version)) --- "
27
38
  fi
28
39
 
29
40
  echo " --- installing $SUITE requirements --- "