newrelic 4.4.0 → 4.7.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 +147 -1
- package/api.js +8 -1
- package/index.js +16 -8
- package/lib/agent.js +7 -1
- package/lib/config/default.js +17 -0
- package/lib/config/env.js +4 -0
- package/lib/config/index.js +21 -5
- 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 +71 -22
- 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/hapi/hapi-17.js +4 -0
- package/lib/metrics/recorders/distributed-trace.js +1 -1
- 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/spans/aggregator.js +3 -4
- package/lib/spans/span-event.js +54 -30
- package/lib/transaction/dt-payload.js +16 -0
- package/lib/transaction/handle.js +1 -1
- package/lib/transaction/index.js +36 -9
- package/lib/transaction/trace/attributes.js +7 -27
- package/lib/transaction/trace/index.js +37 -46
- package/lib/util/byte-limit.js +40 -0
- package/package.json +2 -2
- package/.npmignore +0 -4
package/NEWS.md
CHANGED
|
@@ -1,3 +1,83 @@
|
|
|
1
|
+
### 4.7.0 (2018-07-31):
|
|
2
|
+
|
|
3
|
+
* Added support for distributed tracing.
|
|
4
|
+
|
|
5
|
+
Distributed tracing lets you see the path that a request takes as it travels
|
|
6
|
+
through your distributed system. By showing the distributed activity through a
|
|
7
|
+
unified view, you can troubleshoot and understand a complex system better than
|
|
8
|
+
ever before.
|
|
9
|
+
|
|
10
|
+
Distributed tracing is available with an APM Pro or equivalent subscription.
|
|
11
|
+
To see a complete distributed trace, you need to enable the feature on a set of
|
|
12
|
+
neighboring services. Enabling distributed tracing changes the behavior of some
|
|
13
|
+
New Relic features, so carefully consult the [transition guide](https://docs.newrelic.com/docs/transition-guide-distributed-tracing) before
|
|
14
|
+
you enable this feature.
|
|
15
|
+
|
|
16
|
+
To enable distributed tracing, set `distributed_tracing.enabled` to `true` in
|
|
17
|
+
your `newrelic.js` file, or set `NEW_RELIC_DISTRIBUTED_TRACING_ENABLED` in your
|
|
18
|
+
environment.
|
|
19
|
+
|
|
20
|
+
* Added a warning for too-new versions of Node.js during agent startup.
|
|
21
|
+
|
|
22
|
+
* Appropriately obfuscated SQL statements will now be included in all transaction
|
|
23
|
+
traces.
|
|
24
|
+
|
|
25
|
+
Previously, the agent would only include the SQL statements if the corresponding
|
|
26
|
+
query was sufficiently slow.
|
|
27
|
+
|
|
28
|
+
* Added ability to execute instrumentation functions in the context of the segment
|
|
29
|
+
the segment descriptor is describing.
|
|
30
|
+
|
|
31
|
+
All `record*` methods supplied by all instrumentation shim classes now allow for
|
|
32
|
+
a function to be executed under the context of the segment the record call will
|
|
33
|
+
produce. This may be done by supplying a function in the `inContext` key for the
|
|
34
|
+
segment descriptor passed to the record method.
|
|
35
|
+
|
|
36
|
+
* Reservoirs will now respect setting their size to 0.
|
|
37
|
+
|
|
38
|
+
### 4.6.0 (2018-07-24):
|
|
39
|
+
|
|
40
|
+
* Added full support for Node v10.
|
|
41
|
+
|
|
42
|
+
* Added instrumentation for `crypto.scrypt`.
|
|
43
|
+
|
|
44
|
+
* Added instrumentation for `fs.realpath.native`.
|
|
45
|
+
|
|
46
|
+
* Added instrumentation for `process.setUncaughtExceptionCaptureCallback`.
|
|
47
|
+
|
|
48
|
+
* Updated tests to use `asyncResource.runInAsyncScope` instead of `emitBefore` and
|
|
49
|
+
`emitAfter`
|
|
50
|
+
|
|
51
|
+
* Pulled `distributed_tracing` config value from behind `feature_flag`.
|
|
52
|
+
|
|
53
|
+
### 4.5.1 (2018-07-18):
|
|
54
|
+
|
|
55
|
+
- The agent will now properly remerge event data on collection failure.
|
|
56
|
+
|
|
57
|
+
Previously, the agent wouldn't observe the correct format for remerging, causing
|
|
58
|
+
undefined events to be pushed into the reservoir.
|
|
59
|
+
|
|
60
|
+
### 4.5.0 (2018-07-16):
|
|
61
|
+
|
|
62
|
+
* Feature flags may now be set from environment variables.
|
|
63
|
+
|
|
64
|
+
Using the naming convention `NEW_RELIC_FEATURE_FLAG_<feature flag name in upper
|
|
65
|
+
case>`.
|
|
66
|
+
|
|
67
|
+
* Transaction events may be harvested in two payloads now.
|
|
68
|
+
|
|
69
|
+
This change reduces the occurrence of harvests being rejected due to large
|
|
70
|
+
payloads. Payloads will only be split when they are large (greater than 1/3 the
|
|
71
|
+
maximum).
|
|
72
|
+
|
|
73
|
+
* Updated Hapi v17 instrumentation to wrap `server` export, in addition to `Server`.
|
|
74
|
+
|
|
75
|
+
* `ROOT` segment no longer turns into a span event.
|
|
76
|
+
|
|
77
|
+
* Fixed span collection when transactions are `sampled=false`.
|
|
78
|
+
|
|
79
|
+
* Removed `grandparentId` from spans.
|
|
80
|
+
|
|
1
81
|
### 4.4.0 (2018-07-12):
|
|
2
82
|
|
|
3
83
|
* Added config `utilization` env vars to the `BOOLEAN_VARS` set.
|
|
@@ -9,6 +89,29 @@
|
|
|
9
89
|
|
|
10
90
|
* Added node v10 to the test matrix.
|
|
11
91
|
|
|
92
|
+
* Converted distributed trace `x-newrelic-trace` header name to `newrelic`.
|
|
93
|
+
|
|
94
|
+
* Added support for different transport types in distributed tracing.
|
|
95
|
+
|
|
96
|
+
* Added more tests around priority/sampled attributes on traces and events.
|
|
97
|
+
|
|
98
|
+
* Lazily calculate transaction priority only when needed.
|
|
99
|
+
|
|
100
|
+
* Transaction priority is now truncated to 6 decimal places on generation.
|
|
101
|
+
|
|
102
|
+
* Adaptive sampling now uses the `sampling_target` and
|
|
103
|
+
`sampling_target_period_in_seconds` configuration values.
|
|
104
|
+
|
|
105
|
+
With these configurations, the adaptive sampling window is separated from the
|
|
106
|
+
harvest window.
|
|
107
|
+
|
|
108
|
+
* Removed `nr.tripId` attribute from distributed trace intrinsics.
|
|
109
|
+
|
|
110
|
+
* Default span events to enabled.
|
|
111
|
+
|
|
112
|
+
These are still protected behind `feature_flag.distributed_tracing` which defaults
|
|
113
|
+
to `false`.
|
|
114
|
+
|
|
12
115
|
### 4.3.0 (2018-07-09):
|
|
13
116
|
|
|
14
117
|
* Added `nonce` option for `newrelic.getBrowserTimingHeader()`
|
|
@@ -30,7 +133,7 @@
|
|
|
30
133
|
|
|
31
134
|
* Fixed issue with tracking external requests to default ports.
|
|
32
135
|
|
|
33
|
-
|
|
136
|
+
Special thanks to Ryan King for pinpointing the cause of this issue.
|
|
34
137
|
|
|
35
138
|
* Added extra check for handling arrays of functions when wrapping middleware
|
|
36
139
|
mounters.
|
|
@@ -68,6 +171,25 @@
|
|
|
68
171
|
|
|
69
172
|
* No longer download gcc on test suites that do not require it.
|
|
70
173
|
|
|
174
|
+
* Added `url` parameter to `http` external segments.
|
|
175
|
+
|
|
176
|
+
* Renamed request parameters on external segments.
|
|
177
|
+
|
|
178
|
+
Previously these were named just the parameter name (e.g. `/foo?bar=baz` would
|
|
179
|
+
become the parameter `"bar": "baz"`). Now they are prefixed with
|
|
180
|
+
`request.parameter`. (e.g. `"request.parameter.bar": "baz"`).
|
|
181
|
+
|
|
182
|
+
* Added `EventAggregator` base class.
|
|
183
|
+
|
|
184
|
+
The `ErrorAggregator` class was refactored and most generic event aggregation
|
|
185
|
+
logic was moved to the new `EventAggregator` class.
|
|
186
|
+
|
|
187
|
+
* Added `SpanEvent` and `SpanAggregator` classes.
|
|
188
|
+
|
|
189
|
+
* Added Span event generation to the trace `end` method.
|
|
190
|
+
|
|
191
|
+
* Added Span events to harvest cycle steps.
|
|
192
|
+
|
|
71
193
|
### 4.1.5 (2018-06-11):
|
|
72
194
|
|
|
73
195
|
* Make `require()` statements explicitly reference `package.json` as a `.json` file.
|
|
@@ -110,6 +232,11 @@
|
|
|
110
232
|
result in a false `uninstrumented` status, because the agent would interpret
|
|
111
233
|
`redis.js` as the module itself.
|
|
112
234
|
|
|
235
|
+
* Moved `computeSampled` call to `Transaction` constructor.
|
|
236
|
+
|
|
237
|
+
Previously it was only called in `createDistributedTracePayload`, but this
|
|
238
|
+
gives all transactions a `sampled` value, and potentially a boosted priority.
|
|
239
|
+
|
|
113
240
|
### 4.1.4 (2018-06-04):
|
|
114
241
|
|
|
115
242
|
* Transaction stubs are now created properly in `api#getTransaction`
|
|
@@ -133,6 +260,25 @@
|
|
|
133
260
|
|
|
134
261
|
* Modularlized configuration constants to improve readability.
|
|
135
262
|
|
|
263
|
+
* Added `distributed_tracing` feature flag.
|
|
264
|
+
|
|
265
|
+
* Added `acceptDistributedTracePayload` method to `Transaction`.
|
|
266
|
+
|
|
267
|
+
* Added `createDistributedTracePayload` method to `Transaction`.
|
|
268
|
+
|
|
269
|
+
* Updated `Agent#recordSupportability` to not include `Nodejs/` in the default metric name.
|
|
270
|
+
|
|
271
|
+
* Added distributed tracing methods to `TransactionHandle`.
|
|
272
|
+
|
|
273
|
+
* Added distributed tracing cases for `http` and `other` metric recorders.
|
|
274
|
+
|
|
275
|
+
* Implemented `_addDistributedTraceInstrinsics` on `Transaction`.
|
|
276
|
+
|
|
277
|
+
If the `distributed_tracing` feature flag is enabled, the agent will ignore old
|
|
278
|
+
CAT attributes in favor of distributed trace–related ones.
|
|
279
|
+
|
|
280
|
+
* Added integration tests around better CAT functionality.
|
|
281
|
+
|
|
136
282
|
### 4.1.2 (2018-05-22):
|
|
137
283
|
|
|
138
284
|
* 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]
|
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
|
|
@@ -677,6 +677,12 @@ Agent.prototype._listenForConfigChanges = function _listenForConfigChanges() {
|
|
|
677
677
|
self.transactionSampler.samplingPeriod = period * 1000
|
|
678
678
|
}
|
|
679
679
|
)
|
|
680
|
+
this.config.on(
|
|
681
|
+
'transaction_events.max_samples_per_minute',
|
|
682
|
+
function updateEventSampleLimit(maxSamples) {
|
|
683
|
+
self.events.setLimit(maxSamples)
|
|
684
|
+
}
|
|
685
|
+
)
|
|
680
686
|
}
|
|
681
687
|
|
|
682
688
|
module.exports = Agent
|
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,11 +21,11 @@ var logger = null // Lazy-loaded in `initialize`.
|
|
|
21
21
|
/**
|
|
22
22
|
* CONSTANTS -- we gotta lotta 'em
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const DEFAULT_CONFIG_PATH = require.resolve('./default')
|
|
25
|
+
const DEFAULT_CONFIG = require('./default').config
|
|
26
|
+
const DEFAULT_FILENAME = 'newrelic.js'
|
|
27
|
+
const AZURE_APP_NAME = 'APP_POOL_ID'
|
|
28
|
+
const CONFIG_FILE_LOCATIONS = [
|
|
29
29
|
process.env.NEW_RELIC_HOME,
|
|
30
30
|
process.cwd(),
|
|
31
31
|
process.env.HOME,
|
|
@@ -159,6 +159,7 @@ function Config(config) {
|
|
|
159
159
|
this._fromSpecial()
|
|
160
160
|
|
|
161
161
|
// 4. override config with environment variables
|
|
162
|
+
this._featureFlagsFromEnv()
|
|
162
163
|
this._fromEnvironment()
|
|
163
164
|
|
|
164
165
|
// 5. clean up anything that requires postprocessing
|
|
@@ -847,6 +848,21 @@ Config.prototype._fromSpecial = function _fromSpecial() {
|
|
|
847
848
|
}
|
|
848
849
|
}
|
|
849
850
|
|
|
851
|
+
/**
|
|
852
|
+
* Iterate over all feature flags and check for the corresponding environment variable
|
|
853
|
+
* (of the form NEW_RELIC_FEATURE_FLAG_<feature flag name in upper case>).
|
|
854
|
+
*/
|
|
855
|
+
Config.prototype._featureFlagsFromEnv = function _featureFlagsFromEnv() {
|
|
856
|
+
const flags = Object.keys(feature_flag.prerelease).concat(feature_flag.released)
|
|
857
|
+
const config = this
|
|
858
|
+
flags.forEach(function checkFlag(flag) {
|
|
859
|
+
const envVal = process.env['NEW_RELIC_FEATURE_FLAG_' + flag.toUpperCase()]
|
|
860
|
+
if (envVal) {
|
|
861
|
+
config.feature_flag[flag] = isTruthular(envVal)
|
|
862
|
+
}
|
|
863
|
+
})
|
|
864
|
+
}
|
|
865
|
+
|
|
850
866
|
/**
|
|
851
867
|
* Recursively visit the nodes of the constant containing the mapping between
|
|
852
868
|
* environment variable names, overriding any configuration values that are
|
package/lib/db/tracer.js
CHANGED
|
@@ -46,27 +46,36 @@ QueryTracer.prototype.merge = function merge(tracer) {
|
|
|
46
46
|
|
|
47
47
|
QueryTracer.prototype.addQuery = function addQuery(segment, type, query, trace) {
|
|
48
48
|
const ttConfig = this.config.transaction_tracer
|
|
49
|
-
if (segment.getDurationInMillis() < ttConfig.explain_threshold) {
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
const slowQuery = new SlowQuery(segment, type, query, trace)
|
|
53
49
|
|
|
50
|
+
// If DT is enabled and the segment is part of a sampled transaction
|
|
51
|
+
// (i.e. we are creating a span event for this segment), then we need
|
|
52
|
+
// to collect the sql trace.
|
|
53
|
+
var slowQuery
|
|
54
54
|
switch (ttConfig.record_sql) {
|
|
55
55
|
case 'raw':
|
|
56
|
+
slowQuery = new SlowQuery(segment, type, query, trace)
|
|
56
57
|
logger.trace('recording raw sql')
|
|
57
58
|
segment.parameters.sql = slowQuery.query
|
|
58
59
|
break
|
|
59
60
|
case 'obfuscated':
|
|
61
|
+
slowQuery = new SlowQuery(segment, type, query, trace)
|
|
60
62
|
logger.trace('recording obfuscated sql')
|
|
61
63
|
segment.parameters.sql_obfuscated = slowQuery.obfuscated
|
|
62
64
|
break
|
|
63
65
|
default:
|
|
64
66
|
logger.trace(
|
|
65
|
-
'not
|
|
67
|
+
'not recording sql statement, transaction_tracer.record_sql was set to %s',
|
|
66
68
|
ttConfig.record_sql
|
|
67
69
|
)
|
|
68
70
|
return
|
|
69
71
|
}
|
|
72
|
+
|
|
73
|
+
if (segment.getDurationInMillis() < ttConfig.explain_threshold) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
slowQuery = slowQuery || new SlowQuery(segment, type, query, trace)
|
|
78
|
+
|
|
70
79
|
segment.parameters.backtrace = slowQuery.trace
|
|
71
80
|
|
|
72
81
|
if (!this.config.slow_sql.enabled) {
|
|
@@ -158,7 +167,7 @@ QuerySample.prototype.getParams = function getParams() {
|
|
|
158
167
|
params.database_name = segmentParams.database_name
|
|
159
168
|
}
|
|
160
169
|
|
|
161
|
-
if (this.tracer.config.
|
|
170
|
+
if (this.tracer.config.distributed_tracing.enabled) {
|
|
162
171
|
this.trace.segment.transaction.addDistributedTraceIntrinsics(params)
|
|
163
172
|
}
|
|
164
173
|
|
package/lib/environment.js
CHANGED
|
@@ -305,7 +305,7 @@ function getGlobalPackages(cb) {
|
|
|
305
305
|
* package appears at most once, with all the versions joined into a
|
|
306
306
|
* comma-delimited list.
|
|
307
307
|
*
|
|
308
|
-
* @return {Array.<
|
|
308
|
+
* @return {Array.<string[]>} Sorted list of [name, version] pairs.
|
|
309
309
|
*/
|
|
310
310
|
function flattenVersions(packages) {
|
|
311
311
|
var info = Object.create(null)
|
package/lib/errors/index.js
CHANGED
|
@@ -170,7 +170,7 @@ function _getErrorEventIntrinsicAttrs(transaction, errorClass, message, timestam
|
|
|
170
170
|
attributes["nr.syntheticsMonitorId"] = transaction.syntheticsData.monitorId
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
if (transaction.agent.config.
|
|
173
|
+
if (transaction.agent.config.distributed_tracing.enabled) {
|
|
174
174
|
transaction.addDistributedTraceIntrinsics(attributes)
|
|
175
175
|
} else {
|
|
176
176
|
attributes['nr.referringTransactionGuid'] = transaction.referringTransactionGuid
|
package/lib/feature_flags.js
CHANGED
package/lib/harvest.js
CHANGED
|
@@ -17,7 +17,7 @@ class Harvest {
|
|
|
17
17
|
this._errorEventsQueue = agent.errors.getQueue()
|
|
18
18
|
this._errors = agent.errors.getErrors()
|
|
19
19
|
this._traces = [].concat(agent.traces.syntheticsTraces)
|
|
20
|
-
this._events = agent.events
|
|
20
|
+
this._events = this._splitPayload(agent.events)
|
|
21
21
|
this._queries = agent.queries
|
|
22
22
|
this._spanEventsQueue = agent.spans.getQueue()
|
|
23
23
|
|
|
@@ -74,7 +74,13 @@ class Harvest {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
if (this._events) {
|
|
77
|
-
|
|
77
|
+
for (let i = 0; i < this._events.length; ++i) {
|
|
78
|
+
if (this._events[i]) {
|
|
79
|
+
this.agent.events.merge(
|
|
80
|
+
this._events[i].toMerge
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
78
84
|
}
|
|
79
85
|
if (this._customEvents) {
|
|
80
86
|
this.agent.customEvents.merge(this._customEvents)
|
|
@@ -203,22 +209,24 @@ class Harvest {
|
|
|
203
209
|
}
|
|
204
210
|
|
|
205
211
|
_prepareEvents() {
|
|
212
|
+
const eventAggr = this.agent.events
|
|
213
|
+
|
|
206
214
|
// Create the metrics so they are at least set to 0
|
|
207
215
|
const discarded = this.agent.metrics.getOrCreateMetric(NAMES.EVENTS.DISCARDED)
|
|
208
216
|
const seen = this.agent.metrics.getOrCreateMetric(NAMES.EVENTS.SEEN)
|
|
209
217
|
const sent = this.agent.metrics.getOrCreateMetric(NAMES.EVENTS.SENT)
|
|
210
218
|
|
|
211
|
-
seen.incrementCallCount(
|
|
212
|
-
sent.incrementCallCount(
|
|
219
|
+
seen.incrementCallCount(eventAggr.seen)
|
|
220
|
+
sent.incrementCallCount(eventAggr.sent)
|
|
213
221
|
|
|
214
|
-
//
|
|
215
|
-
const diff =
|
|
222
|
+
// If we had to limit events and sample them, emit a warning
|
|
223
|
+
const diff = eventAggr.overflow()
|
|
216
224
|
discarded.incrementCallCount(diff)
|
|
217
225
|
if (diff > 0) {
|
|
218
226
|
logger.warn(
|
|
219
227
|
'analytics event overflow, dropped %d events; try increasing your limit above %d',
|
|
220
228
|
diff,
|
|
221
|
-
|
|
229
|
+
eventAggr.limit
|
|
222
230
|
)
|
|
223
231
|
}
|
|
224
232
|
}
|
|
@@ -351,24 +359,20 @@ class Harvest {
|
|
|
351
359
|
return setImmediate(callback)
|
|
352
360
|
}
|
|
353
361
|
|
|
354
|
-
const metrics = {
|
|
355
|
-
reservoir_size: this._events.limit,
|
|
356
|
-
events_seen: this._events.seen
|
|
357
|
-
}
|
|
358
|
-
const payload = [
|
|
359
|
-
this.agent.config.run_id,
|
|
360
|
-
metrics,
|
|
361
|
-
this._events.toArray()
|
|
362
|
-
]
|
|
363
|
-
|
|
364
|
-
// Send data to collector
|
|
365
362
|
const self = this
|
|
366
363
|
const agent = this.agent
|
|
367
|
-
|
|
368
|
-
|
|
364
|
+
a.eachOfSeries(this._events, function sendEachPayload(obj, i, cb) {
|
|
365
|
+
const payload = obj.payload
|
|
366
|
+
agent.collector.analyticsEvents(payload, function onAnalyticsEvents(err) {
|
|
367
|
+
if (self._shouldClearData(err, 'events')) {
|
|
368
|
+
self._events[i] = null
|
|
369
|
+
}
|
|
370
|
+
cb(err)
|
|
371
|
+
})
|
|
372
|
+
}, function afterAllSent(err) {
|
|
373
|
+
if (!err) {
|
|
369
374
|
self._events = null
|
|
370
375
|
}
|
|
371
|
-
|
|
372
376
|
callback(err)
|
|
373
377
|
})
|
|
374
378
|
}
|
|
@@ -468,7 +472,7 @@ class Harvest {
|
|
|
468
472
|
|
|
469
473
|
_sendSpanEvents(callback) {
|
|
470
474
|
const config = this.agent.config
|
|
471
|
-
if (!config.span_events.enabled || !config.
|
|
475
|
+
if (!config.span_events.enabled || !config.distributed_tracing.enabled) {
|
|
472
476
|
logger.debug('Span events collection disabled.')
|
|
473
477
|
this._spanEventsQueues = null
|
|
474
478
|
return setImmediate(callback)
|
|
@@ -511,6 +515,51 @@ class Harvest {
|
|
|
511
515
|
logger.warn('Failed to send %j; re-sampling.', name)
|
|
512
516
|
return false
|
|
513
517
|
}
|
|
518
|
+
|
|
519
|
+
_splitPayload(queue) {
|
|
520
|
+
// If we're less than 1/3 full, don't bother splitting the payload.
|
|
521
|
+
if (queue.length === 0) {
|
|
522
|
+
return []
|
|
523
|
+
}
|
|
524
|
+
if (queue.length < queue.limit / 3) {
|
|
525
|
+
return [{
|
|
526
|
+
toMerge: queue,
|
|
527
|
+
payload: [
|
|
528
|
+
this.agent.config.run_id,
|
|
529
|
+
{reservoir_size: queue.limit, events_seen: queue.seen},
|
|
530
|
+
queue.toArray()
|
|
531
|
+
]
|
|
532
|
+
}]
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Our payload is large, so split it in half.
|
|
536
|
+
// TODO: update this to pull the priority off the event when DT is released
|
|
537
|
+
const events = queue.getRawEvents()
|
|
538
|
+
const size = Math.floor(queue.length / 2)
|
|
539
|
+
const limit = Math.floor(queue.limit / 2)
|
|
540
|
+
const seen = Math.floor(queue.seen / 2)
|
|
541
|
+
const firstHalf = events.splice(0, size)
|
|
542
|
+
|
|
543
|
+
return [{
|
|
544
|
+
toMerge: firstHalf,
|
|
545
|
+
payload: [
|
|
546
|
+
this.agent.config.run_id,
|
|
547
|
+
{reservoir_size: limit, events_seen: seen},
|
|
548
|
+
firstHalf.map(rawEventsToValues)
|
|
549
|
+
]
|
|
550
|
+
}, {
|
|
551
|
+
toMerge: events,
|
|
552
|
+
payload: [
|
|
553
|
+
this.agent.config.run_id,
|
|
554
|
+
{reservoir_size: queue.limit - limit, events_seen: queue.seen - seen},
|
|
555
|
+
events.map(rawEventsToValues)
|
|
556
|
+
]
|
|
557
|
+
}]
|
|
558
|
+
|
|
559
|
+
function rawEventsToValues(ev) {
|
|
560
|
+
return ev.value
|
|
561
|
+
}
|
|
562
|
+
}
|
|
514
563
|
}
|
|
515
564
|
|
|
516
565
|
module.exports = Harvest
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
var record = require('../../metrics/recorders/generic
|
|
4
|
-
var NAMES = require('../../metrics/names
|
|
3
|
+
var record = require('../../metrics/recorders/generic')
|
|
4
|
+
var NAMES = require('../../metrics/names')
|
|
5
5
|
var wrap = require('../../shimmer').wrapMethod
|
|
6
6
|
|
|
7
7
|
module.exports = initialize
|
|
@@ -46,6 +46,7 @@ function initialize(agent, fs) {
|
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
wrap(fs, 'fs', methods, segment)
|
|
49
|
+
wrap(fs.realpath, 'fs.realpath', 'native', wrapRealPathNative)
|
|
49
50
|
wrap(fs, 'fs', uninstrumented, agent.tracer.wrapFunctionNoSegment.bind(agent.tracer))
|
|
50
51
|
wrap(fs, 'fs', ['watch'], wrapWatch)
|
|
51
52
|
wrap(fs, 'fs', ['watchFile'], wrapWatchFile)
|
|
@@ -54,6 +55,10 @@ function initialize(agent, fs) {
|
|
|
54
55
|
return agent.tracer.wrapFunctionLast(NAMES.FS.PREFIX + method, record, fn)
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
function wrapRealPathNative(fn) {
|
|
59
|
+
return segment(fn, 'realpath.native')
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
function wrapWatch(fn) {
|
|
58
63
|
return function wrappedWatch() {
|
|
59
64
|
var args = agent.tracer.slice(arguments)
|
|
@@ -8,6 +8,8 @@ module.exports = initialize
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
function initialize(agent) {
|
|
11
|
+
let exceptionCallbackRegistered = false
|
|
12
|
+
|
|
11
13
|
// `_fatalException` is an undocumented feature of domains, introduced in
|
|
12
14
|
// Node.js v0.8. We use `_fatalException` because wrapping it will not
|
|
13
15
|
// potentially change the behavior of the server unlike listening for
|
|
@@ -16,7 +18,7 @@ function initialize(agent) {
|
|
|
16
18
|
return function wrappedFatalException(error) {
|
|
17
19
|
// Only record the error if we are not currently within an instrumented
|
|
18
20
|
// domain.
|
|
19
|
-
if (!process.domain) {
|
|
21
|
+
if (!process.domain && !exceptionCallbackRegistered) {
|
|
20
22
|
agent.errors.add(null, error)
|
|
21
23
|
agent.tracer.segment = null
|
|
22
24
|
}
|
|
@@ -45,6 +47,20 @@ function initialize(agent) {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
shimmer.wrapMethod(
|
|
51
|
+
process,
|
|
52
|
+
'process',
|
|
53
|
+
'setUncaughtExceptionCaptureCallback',
|
|
54
|
+
wrapUncaughtExceptionCallback
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
function wrapUncaughtExceptionCallback(original) {
|
|
58
|
+
return function wrapped(fn) {
|
|
59
|
+
exceptionCallbackRegistered = fn !== null
|
|
60
|
+
return original.apply(this, arguments)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
48
64
|
// This will initialize the most optimal native-promise instrumentation that
|
|
49
65
|
// we have available.
|
|
50
66
|
asyncHooks(agent)
|