newrelic 4.5.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NEWS.md +153 -1
- package/api.js +8 -1
- package/bin/compare-bench-results.js +159 -0
- package/bin/run-bench.js +87 -44
- package/index.js +16 -8
- package/lib/agent.js +1 -1
- package/lib/collector/remote-method.js +12 -0
- package/lib/config/default.js +17 -0
- package/lib/config/env.js +4 -0
- package/lib/config/index.js +3 -0
- package/lib/db/tracer.js +15 -6
- package/lib/environment.js +1 -1
- package/lib/errors/index.js +1 -1
- package/lib/feature_flags.js +0 -1
- package/lib/harvest.js +36 -18
- package/lib/instrumentation/core/crypto.js +2 -1
- package/lib/instrumentation/core/fs.js +7 -2
- package/lib/instrumentation/core/globals.js +17 -1
- package/lib/instrumentation/core/http-outbound.js +102 -3
- package/lib/instrumentation/core/http.js +6 -96
- package/lib/instrumentation/mongodb.js +158 -115
- package/lib/metrics/recorders/http.js +1 -1
- package/lib/metrics/recorders/other.js +1 -1
- package/lib/priority-queue.js +5 -2
- package/lib/shim/message-shim.js +5 -4
- package/lib/shim/shim.js +14 -3
- package/lib/shim/specs/index.js +1 -0
- package/lib/shim/transaction-shim.js +3 -3
- package/lib/shimmer.js +3 -0
- package/lib/transaction/dt-payload.js +16 -0
- package/lib/transaction/handle.js +1 -1
- package/lib/transaction/index.js +8 -4
- package/lib/transaction/trace/index.js +31 -38
- package/package.json +3 -2
- package/.npmignore +0 -4
package/NEWS.md
CHANGED
|
@@ -1,3 +1,83 @@
|
|
|
1
|
+
### 4.8.0 (2018-08-13):
|
|
2
|
+
|
|
3
|
+
* Added JSON-formatted output to benchmarks to enable automated benchmark comparison.
|
|
4
|
+
|
|
5
|
+
* Updated the benchmark runner to measure specifically userland CPU overhead.
|
|
6
|
+
|
|
7
|
+
* Added DatastoreShim benchmarks.
|
|
8
|
+
|
|
9
|
+
* Fixed MongoDB instrumentation for driver versions greater than 3.0.6.
|
|
10
|
+
|
|
11
|
+
Mongo 3.0.6 removed metadata the Agent relied upon to instrument the driver. This
|
|
12
|
+
fixes that by going back to the old method of manually listing all objects and
|
|
13
|
+
methods to instrument.
|
|
14
|
+
|
|
15
|
+
* Implemented enforcement of `max_payload_size_in_bytes` config value.
|
|
16
|
+
|
|
17
|
+
Any payload during the harvest sequence that exceeds the configured limit will
|
|
18
|
+
be discarded.
|
|
19
|
+
|
|
20
|
+
* Updated MySQL versioned tests to run against the latest release.
|
|
21
|
+
|
|
22
|
+
### 4.7.0 (2018-07-31):
|
|
23
|
+
|
|
24
|
+
* Added support for distributed tracing.
|
|
25
|
+
|
|
26
|
+
Distributed tracing lets you see the path that a request takes as it travels
|
|
27
|
+
through your distributed system. By showing the distributed activity through a
|
|
28
|
+
unified view, you can troubleshoot and understand a complex system better than
|
|
29
|
+
ever before.
|
|
30
|
+
|
|
31
|
+
Distributed tracing is available with an APM Pro or equivalent subscription.
|
|
32
|
+
To see a complete distributed trace, you need to enable the feature on a set of
|
|
33
|
+
neighboring services. Enabling distributed tracing changes the behavior of some
|
|
34
|
+
New Relic features, so carefully consult the [transition guide](https://docs.newrelic.com/docs/transition-guide-distributed-tracing) before
|
|
35
|
+
you enable this feature.
|
|
36
|
+
|
|
37
|
+
To enable distributed tracing, set `distributed_tracing.enabled` to `true` in
|
|
38
|
+
your `newrelic.js` file, or set `NEW_RELIC_DISTRIBUTED_TRACING_ENABLED` in your
|
|
39
|
+
environment.
|
|
40
|
+
|
|
41
|
+
* Added a warning for too-new versions of Node.js during agent startup.
|
|
42
|
+
|
|
43
|
+
* Appropriately obfuscated SQL statements will now be included in all transaction
|
|
44
|
+
traces.
|
|
45
|
+
|
|
46
|
+
Previously, the agent would only include the SQL statements if the corresponding
|
|
47
|
+
query was sufficiently slow.
|
|
48
|
+
|
|
49
|
+
* Added ability to execute instrumentation functions in the context of the segment
|
|
50
|
+
the segment descriptor is describing.
|
|
51
|
+
|
|
52
|
+
All `record*` methods supplied by all instrumentation shim classes now allow for
|
|
53
|
+
a function to be executed under the context of the segment the record call will
|
|
54
|
+
produce. This may be done by supplying a function in the `inContext` key for the
|
|
55
|
+
segment descriptor passed to the record method.
|
|
56
|
+
|
|
57
|
+
* Reservoirs will now respect setting their size to 0.
|
|
58
|
+
|
|
59
|
+
### 4.6.0 (2018-07-24):
|
|
60
|
+
|
|
61
|
+
* Added full support for Node v10.
|
|
62
|
+
|
|
63
|
+
* Added instrumentation for `crypto.scrypt`.
|
|
64
|
+
|
|
65
|
+
* Added instrumentation for `fs.realpath.native`.
|
|
66
|
+
|
|
67
|
+
* Added instrumentation for `process.setUncaughtExceptionCaptureCallback`.
|
|
68
|
+
|
|
69
|
+
* Updated tests to use `asyncResource.runInAsyncScope` instead of `emitBefore` and
|
|
70
|
+
`emitAfter`
|
|
71
|
+
|
|
72
|
+
* Pulled `distributed_tracing` config value from behind `feature_flag`.
|
|
73
|
+
|
|
74
|
+
### 4.5.1 (2018-07-18):
|
|
75
|
+
|
|
76
|
+
- The agent will now properly remerge event data on collection failure.
|
|
77
|
+
|
|
78
|
+
Previously, the agent wouldn't observe the correct format for remerging, causing
|
|
79
|
+
undefined events to be pushed into the reservoir.
|
|
80
|
+
|
|
1
81
|
### 4.5.0 (2018-07-16):
|
|
2
82
|
|
|
3
83
|
* Feature flags may now be set from environment variables.
|
|
@@ -13,6 +93,12 @@
|
|
|
13
93
|
|
|
14
94
|
* Updated Hapi v17 instrumentation to wrap `server` export, in addition to `Server`.
|
|
15
95
|
|
|
96
|
+
* `ROOT` segment no longer turns into a span event.
|
|
97
|
+
|
|
98
|
+
* Fixed span collection when transactions are `sampled=false`.
|
|
99
|
+
|
|
100
|
+
* Removed `grandparentId` from spans.
|
|
101
|
+
|
|
16
102
|
### 4.4.0 (2018-07-12):
|
|
17
103
|
|
|
18
104
|
* Added config `utilization` env vars to the `BOOLEAN_VARS` set.
|
|
@@ -24,6 +110,29 @@
|
|
|
24
110
|
|
|
25
111
|
* Added node v10 to the test matrix.
|
|
26
112
|
|
|
113
|
+
* Converted distributed trace `x-newrelic-trace` header name to `newrelic`.
|
|
114
|
+
|
|
115
|
+
* Added support for different transport types in distributed tracing.
|
|
116
|
+
|
|
117
|
+
* Added more tests around priority/sampled attributes on traces and events.
|
|
118
|
+
|
|
119
|
+
* Lazily calculate transaction priority only when needed.
|
|
120
|
+
|
|
121
|
+
* Transaction priority is now truncated to 6 decimal places on generation.
|
|
122
|
+
|
|
123
|
+
* Adaptive sampling now uses the `sampling_target` and
|
|
124
|
+
`sampling_target_period_in_seconds` configuration values.
|
|
125
|
+
|
|
126
|
+
With these configurations, the adaptive sampling window is separated from the
|
|
127
|
+
harvest window.
|
|
128
|
+
|
|
129
|
+
* Removed `nr.tripId` attribute from distributed trace intrinsics.
|
|
130
|
+
|
|
131
|
+
* Default span events to enabled.
|
|
132
|
+
|
|
133
|
+
These are still protected behind `feature_flag.distributed_tracing` which defaults
|
|
134
|
+
to `false`.
|
|
135
|
+
|
|
27
136
|
### 4.3.0 (2018-07-09):
|
|
28
137
|
|
|
29
138
|
* Added `nonce` option for `newrelic.getBrowserTimingHeader()`
|
|
@@ -45,7 +154,7 @@
|
|
|
45
154
|
|
|
46
155
|
* Fixed issue with tracking external requests to default ports.
|
|
47
156
|
|
|
48
|
-
|
|
157
|
+
Special thanks to Ryan King for pinpointing the cause of this issue.
|
|
49
158
|
|
|
50
159
|
* Added extra check for handling arrays of functions when wrapping middleware
|
|
51
160
|
mounters.
|
|
@@ -83,6 +192,25 @@
|
|
|
83
192
|
|
|
84
193
|
* No longer download gcc on test suites that do not require it.
|
|
85
194
|
|
|
195
|
+
* Added `url` parameter to `http` external segments.
|
|
196
|
+
|
|
197
|
+
* Renamed request parameters on external segments.
|
|
198
|
+
|
|
199
|
+
Previously these were named just the parameter name (e.g. `/foo?bar=baz` would
|
|
200
|
+
become the parameter `"bar": "baz"`). Now they are prefixed with
|
|
201
|
+
`request.parameter`. (e.g. `"request.parameter.bar": "baz"`).
|
|
202
|
+
|
|
203
|
+
* Added `EventAggregator` base class.
|
|
204
|
+
|
|
205
|
+
The `ErrorAggregator` class was refactored and most generic event aggregation
|
|
206
|
+
logic was moved to the new `EventAggregator` class.
|
|
207
|
+
|
|
208
|
+
* Added `SpanEvent` and `SpanAggregator` classes.
|
|
209
|
+
|
|
210
|
+
* Added Span event generation to the trace `end` method.
|
|
211
|
+
|
|
212
|
+
* Added Span events to harvest cycle steps.
|
|
213
|
+
|
|
86
214
|
### 4.1.5 (2018-06-11):
|
|
87
215
|
|
|
88
216
|
* Make `require()` statements explicitly reference `package.json` as a `.json` file.
|
|
@@ -125,6 +253,11 @@
|
|
|
125
253
|
result in a false `uninstrumented` status, because the agent would interpret
|
|
126
254
|
`redis.js` as the module itself.
|
|
127
255
|
|
|
256
|
+
* Moved `computeSampled` call to `Transaction` constructor.
|
|
257
|
+
|
|
258
|
+
Previously it was only called in `createDistributedTracePayload`, but this
|
|
259
|
+
gives all transactions a `sampled` value, and potentially a boosted priority.
|
|
260
|
+
|
|
128
261
|
### 4.1.4 (2018-06-04):
|
|
129
262
|
|
|
130
263
|
* Transaction stubs are now created properly in `api#getTransaction`
|
|
@@ -148,6 +281,25 @@
|
|
|
148
281
|
|
|
149
282
|
* Modularlized configuration constants to improve readability.
|
|
150
283
|
|
|
284
|
+
* Added `distributed_tracing` feature flag.
|
|
285
|
+
|
|
286
|
+
* Added `acceptDistributedTracePayload` method to `Transaction`.
|
|
287
|
+
|
|
288
|
+
* Added `createDistributedTracePayload` method to `Transaction`.
|
|
289
|
+
|
|
290
|
+
* Updated `Agent#recordSupportability` to not include `Nodejs/` in the default metric name.
|
|
291
|
+
|
|
292
|
+
* Added distributed tracing methods to `TransactionHandle`.
|
|
293
|
+
|
|
294
|
+
* Added distributed tracing cases for `http` and `other` metric recorders.
|
|
295
|
+
|
|
296
|
+
* Implemented `_addDistributedTraceInstrinsics` on `Transaction`.
|
|
297
|
+
|
|
298
|
+
If the `distributed_tracing` feature flag is enabled, the agent will ignore old
|
|
299
|
+
CAT attributes in favor of distributed trace–related ones.
|
|
300
|
+
|
|
301
|
+
* Added integration tests around better CAT functionality.
|
|
302
|
+
|
|
151
303
|
### 4.1.2 (2018-05-22):
|
|
152
304
|
|
|
153
305
|
* Fixed access to properties on promisified methods.
|
package/api.js
CHANGED
|
@@ -702,6 +702,13 @@ function createTracer(name, callback) {
|
|
|
702
702
|
return arity.fixArity(callback, tracer.bindFunction(callback, segment, true))
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
+
/**
|
|
706
|
+
* @callback startSegmentCallback
|
|
707
|
+
* @param {function} cb
|
|
708
|
+
* The function to time with the created segment.
|
|
709
|
+
* @return {Promise=} Returns a promise if cb returns a promise.
|
|
710
|
+
*/
|
|
711
|
+
|
|
705
712
|
/**
|
|
706
713
|
* Wraps the given handler in a segment which may optionally be turned into a
|
|
707
714
|
* metric.
|
|
@@ -720,7 +727,7 @@ function createTracer(name, callback) {
|
|
|
720
727
|
* up on the transaction breakdown table and server breakdown graph. Segments
|
|
721
728
|
* just show up in transaction traces.
|
|
722
729
|
*
|
|
723
|
-
* @param {
|
|
730
|
+
* @param {startSegmentCallback} handler
|
|
724
731
|
* The function to track as a segment.
|
|
725
732
|
*
|
|
726
733
|
* @param {function} [callback]
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
'</details>'
|
|
98
|
+
].join('\n')
|
|
99
|
+
}).join('\n\n-----------------------------------------------------------\n\n')
|
|
100
|
+
|
|
101
|
+
if (warnings.length) {
|
|
102
|
+
console.log('### WARNINGS')
|
|
103
|
+
console.log(warnings.join('\n'))
|
|
104
|
+
console.log('')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log(`### Benchmark Results: ${passMark(allPassing)}`)
|
|
108
|
+
console.log('')
|
|
109
|
+
console.log('### Details')
|
|
110
|
+
console.log(details)
|
|
111
|
+
|
|
112
|
+
if (!allPassing) {
|
|
113
|
+
process.exitCode = -1
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
function diffArrays(a, b) {
|
|
118
|
+
return a.filter((elem) => !b.includes(elem))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function compareResults(base, down) {
|
|
122
|
+
const delta = base.mean - down.mean
|
|
123
|
+
const deltaPercent = delta / base.mean
|
|
124
|
+
return delta < 1 || deltaPercent < 2
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function passMark(passes) {
|
|
128
|
+
return passes ? '✔' : '✘'
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function formatResults(base, down) {
|
|
132
|
+
return [
|
|
133
|
+
`- ${formatField('numSamples', base, down)}`,
|
|
134
|
+
`- ${formatField('mean', base, down)}`,
|
|
135
|
+
`- ${formatField('stdDev', base, down)}`,
|
|
136
|
+
`- ${formatField('max', base, down)}`,
|
|
137
|
+
`- ${formatField('min', base, down)}`,
|
|
138
|
+
`- ${formatField('5thPercentile', base, down)}`,
|
|
139
|
+
`- ${formatField('95thPercentile', base, down)}`,
|
|
140
|
+
`- ${formatField('median', base, down)}`,
|
|
141
|
+
].join('\n')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function formatField(field, base, down) {
|
|
145
|
+
const baseValue = base[field]
|
|
146
|
+
const downValue = down[field]
|
|
147
|
+
const diffValue = baseValue - downValue
|
|
148
|
+
const diffPercent = (100 * diffValue / baseValue).toFixed(2)
|
|
149
|
+
const prefix = diffValue >= 0 ? '+' : ''
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
`${field}: ${fixValue(baseValue)} - ${fixValue(downValue)} =` +
|
|
153
|
+
` ${fixValue(diffValue)} (${prefix}${diffPercent}%)`
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function fixValue(value) {
|
|
158
|
+
return value % 1 ? value.toFixed(5) : value
|
|
159
|
+
}
|
package/bin/run-bench.js
CHANGED
|
@@ -36,54 +36,97 @@ if (tests.length === 0 && globs.length === 0) {
|
|
|
36
36
|
)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return cb(err)
|
|
79
|
+
a.series([
|
|
80
|
+
function resolveGlobs(cb) {
|
|
81
|
+
if (!globs.length) {
|
|
82
|
+
return cb()
|
|
50
83
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
cb()
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
])
|
|
128
|
+
}
|
|
129
|
+
], () => {
|
|
130
|
+
printer.finish()
|
|
131
|
+
})
|
|
132
|
+
}
|
package/index.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
// Record opening times before loading any other files.
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const preAgentTime = process.uptime()
|
|
5
|
+
const agentStart = Date.now()
|
|
6
6
|
|
|
7
7
|
// Load unwrapped core now to ensure it gets the freshest properties.
|
|
8
8
|
require('./lib/util/unwrapped-core')
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const featureFlags = require('./lib/feature_flags').prerelease
|
|
11
|
+
const psemver = require('./lib/util/process-version')
|
|
12
|
+
let logger = require('./lib/logger') // Gets re-loaded after initialization.
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const pkgJSON = require('./package.json')
|
|
16
16
|
logger.info(
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
'Using New Relic for Node.js. Agent version: %s; Node version: %s.',
|
|
18
|
+
pkgJSON.version,
|
|
19
|
+
process.version
|
|
19
20
|
)
|
|
20
21
|
|
|
21
22
|
if (require.cache.__NR_cache) {
|
|
@@ -49,6 +50,13 @@ function initialize() {
|
|
|
49
50
|
|
|
50
51
|
logger.error(message)
|
|
51
52
|
throw new Error(message)
|
|
53
|
+
} else if (!psemver.satisfies(pkgJSON.engines.node)) {
|
|
54
|
+
logger.warn(
|
|
55
|
+
'New Relic for Node.js %s has not been tested on Node.js %s. Please ' +
|
|
56
|
+
'update the agent or downgrade your version of Node.js',
|
|
57
|
+
pkgJSON.version,
|
|
58
|
+
process.version
|
|
59
|
+
)
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
logger.debug("Current working directory at module load is %s.", process.cwd())
|
package/lib/agent.js
CHANGED
|
@@ -516,7 +516,7 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
|
|
|
516
516
|
|
|
517
517
|
// If CAT is enabled, extract the data gleened from the CAT headers.
|
|
518
518
|
if (this.config.cross_application_tracer.enabled) {
|
|
519
|
-
if (this.config.
|
|
519
|
+
if (this.config.distributed_tracing.enabled) {
|
|
520
520
|
transaction.addDistributedTraceIntrinsics(intrinsicAttributes)
|
|
521
521
|
if (transaction.parentSpanId) {
|
|
522
522
|
intrinsicAttributes.parentSpanId = transaction.parentSpanId
|
|
@@ -10,6 +10,7 @@ var stringify = require('json-stringify-safe')
|
|
|
10
10
|
var Sink = require('../util/stream-sink')
|
|
11
11
|
var agents = require('./http-agents')
|
|
12
12
|
var certificates = require('./ssl/certificates')
|
|
13
|
+
const isValidLength = require('../util/byte-limit').isValidLength
|
|
13
14
|
|
|
14
15
|
/*
|
|
15
16
|
*
|
|
@@ -147,8 +148,19 @@ RemoteMethod.prototype._safeRequest = function _safeRequest(options) {
|
|
|
147
148
|
var protocol = 'https'
|
|
148
149
|
var logConfig = this._config.logging
|
|
149
150
|
var auditLog = this._config.audit_log
|
|
151
|
+
const maxPayloadSize = this._config.max_payload_size_in_bytes
|
|
150
152
|
var level = 'trace'
|
|
151
153
|
|
|
154
|
+
if (!isValidLength(options.body, maxPayloadSize + 1)) {
|
|
155
|
+
logger.warn(
|
|
156
|
+
'The payload size %d being sent to method %s exceeded the maximum size of %d',
|
|
157
|
+
Buffer.byteLength(options.body, 'utf8'),
|
|
158
|
+
this.name,
|
|
159
|
+
maxPayloadSize
|
|
160
|
+
)
|
|
161
|
+
throw new Error('Maximum payload size exceeded')
|
|
162
|
+
}
|
|
163
|
+
|
|
152
164
|
// If trace level is not explicity enabled check to see if the audit log is
|
|
153
165
|
// enabled.
|
|
154
166
|
if (logConfig != null && logConfig.level !== 'trace' && auditLog.enabled) {
|
package/lib/config/default.js
CHANGED
|
@@ -791,6 +791,23 @@ exports.config = {
|
|
|
791
791
|
enabled: true
|
|
792
792
|
},
|
|
793
793
|
|
|
794
|
+
/**
|
|
795
|
+
* Controls the method of cross agent tracing in the agent.
|
|
796
|
+
* Distributed tracing lets you see the path that a request takes through your
|
|
797
|
+
* distributed system. Enabling distributed tracing changes the behavior of some
|
|
798
|
+
* New Relic features, so carefully consult the transition guide before you enable
|
|
799
|
+
* this feature: https://docs.newrelic.com/docs/transition-guide-distributed-tracing
|
|
800
|
+
* Default is false.
|
|
801
|
+
*/
|
|
802
|
+
distributed_tracing: {
|
|
803
|
+
/**
|
|
804
|
+
* Enables/disables distributed tracing.
|
|
805
|
+
*
|
|
806
|
+
* @env NEW_RELIC_DISTRIBUTED_TRACING_ENABLED
|
|
807
|
+
*/
|
|
808
|
+
enabled: false
|
|
809
|
+
},
|
|
810
|
+
|
|
794
811
|
/**
|
|
795
812
|
* Controls the use of cross-application tracing.
|
|
796
813
|
*
|
package/lib/config/env.js
CHANGED
|
@@ -114,6 +114,9 @@ const ENV_MAPPING = {
|
|
|
114
114
|
span_events: {
|
|
115
115
|
enabled: 'NEW_RELIC_SPAN_EVENTS_ENABLED'
|
|
116
116
|
},
|
|
117
|
+
distributed_tracing: {
|
|
118
|
+
enabled: 'NEW_RELIC_DISTRIBUTED_TRACING_ENABLED'
|
|
119
|
+
},
|
|
117
120
|
message_tracer: {
|
|
118
121
|
segment_parameters: {
|
|
119
122
|
enabled: 'NEW_RELIC_MESSAGE_TRACER_SEGMENT_PARAMETERS_ENABLED'
|
|
@@ -167,6 +170,7 @@ const BOOLEAN_VARS = new Set([
|
|
|
167
170
|
'NEW_RELIC_HIGH_SECURITY',
|
|
168
171
|
'NEW_RELIC_SLOW_SQL_ENABLED',
|
|
169
172
|
'NEW_RELIC_SPAN_EVENTS_ENABLED',
|
|
173
|
+
'NEW_RELIC_DISTRIBUTED_TRACING_ENABLED',
|
|
170
174
|
'NEW_RELIC_LOG_ENABLED',
|
|
171
175
|
'NEW_RELIC_AUDIT_LOG_ENABLED',
|
|
172
176
|
'NEW_RELIC_DATASTORE_DATABASE_NAME_REPORTING_ENABLED',
|
package/lib/config/index.js
CHANGED
|
@@ -21,6 +21,7 @@ var logger = null // Lazy-loaded in `initialize`.
|
|
|
21
21
|
/**
|
|
22
22
|
* CONSTANTS -- we gotta lotta 'em
|
|
23
23
|
*/
|
|
24
|
+
const DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES = 1000000
|
|
24
25
|
const DEFAULT_CONFIG_PATH = require.resolve('./default')
|
|
25
26
|
const DEFAULT_CONFIG = require('./default').config
|
|
26
27
|
const DEFAULT_FILENAME = 'newrelic.js'
|
|
@@ -126,6 +127,7 @@ function Config(config) {
|
|
|
126
127
|
this.trusted_account_key = null
|
|
127
128
|
this.sampling_target = 10
|
|
128
129
|
this.sampling_target_period_in_seconds = 60
|
|
130
|
+
this.max_payload_size_in_bytes = DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES
|
|
129
131
|
|
|
130
132
|
// how frequently harvester runs
|
|
131
133
|
this.data_report_period = 60
|
|
@@ -273,6 +275,7 @@ Config.prototype._fromServer = function _fromServer(params, key) {
|
|
|
273
275
|
case 'collect_errors':
|
|
274
276
|
case 'collect_traces':
|
|
275
277
|
case 'product_level':
|
|
278
|
+
case 'max_payload_size_in_bytes':
|
|
276
279
|
case 'sampling_target':
|
|
277
280
|
case 'sampling_target_period_in_seconds':
|
|
278
281
|
case 'trusted_account_ids':
|