newrelic 5.3.0 → 5.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +3 -4
- package/NEWS.md +91 -0
- package/api.js +27 -3
- package/index.js +24 -24
- package/lib/adaptive-sampler.js +8 -9
- package/lib/attributes.js +39 -20
- package/lib/collector/facts.js +6 -1
- package/lib/collector/remote-method.js +1 -1
- package/lib/config/attribute-filter.js +43 -13
- package/lib/config/default.js +5 -1
- package/lib/config/env.js +1 -1
- package/lib/config/index.js +40 -5
- package/lib/errors/index.js +1 -2
- package/lib/header-attributes.js +0 -2
- package/lib/instrumentation/core/http-outbound.js +13 -1
- package/lib/instrumentation/core/http.js +0 -6
- package/lib/instrumentation/memcached.js +3 -2
- package/lib/serverless/aws-lambda.js +1 -6
- package/lib/shim/datastore-shim.js +10 -8
- package/lib/shim/message-shim.js +2 -4
- package/lib/shim/shim.js +12 -0
- package/lib/spans/span-event.js +107 -93
- package/lib/timer.js +3 -1
- package/lib/transaction/index.js +3 -5
- package/lib/transaction/trace/exclusive-time-calculator.js +145 -0
- package/lib/transaction/trace/index.js +18 -29
- package/lib/transaction/trace/segment.js +63 -74
- package/lib/util/attribute-types.js +21 -0
- package/lib/util/byte-limit.js +38 -9
- package/package.json +1 -1
- package/lib/util/sum-children.js +0 -52
package/CONTRIBUTING.md
CHANGED
|
@@ -37,8 +37,7 @@ and not ready for general-purpose use.
|
|
|
37
37
|
|
|
38
38
|
### Setup
|
|
39
39
|
|
|
40
|
-
To run the tests you need
|
|
41
|
-
binary, and some services:
|
|
40
|
+
To run the tests you need an openssl command-line binary, and some services:
|
|
42
41
|
|
|
43
42
|
* Cassandra
|
|
44
43
|
* Memcached
|
|
@@ -50,7 +49,7 @@ binary, and some services:
|
|
|
50
49
|
If you have these all running locally on the standard ports, then you are good
|
|
51
50
|
to go. However, the suggested path is to use [Docker](http://www.docker.com).
|
|
52
51
|
If you use OS X or Windows, use Docker Machine, which can be installed as a part of
|
|
53
|
-
[Docker Toolbox](https://www.docker.com/docker-toolbox). Then, run `
|
|
52
|
+
[Docker Toolbox](https://www.docker.com/docker-toolbox). Then, run `npm run services`
|
|
54
53
|
to start docker containers for each of the above services.
|
|
55
54
|
|
|
56
55
|
If you have these services available on non-standard ports or elsewhere on your
|
|
@@ -75,7 +74,7 @@ tests if all of the unit tests pass.
|
|
|
75
74
|
If you don't feel like dealing with the hassle of setting up the servers, just
|
|
76
75
|
the unit tests can be run with:
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
npm run unit
|
|
79
78
|
|
|
80
79
|
### Writing tests
|
|
81
80
|
|
package/NEWS.md
CHANGED
|
@@ -1,3 +1,94 @@
|
|
|
1
|
+
### 5.6.2 (2019-03-25):
|
|
2
|
+
|
|
3
|
+
* Agent now respects attribute type restrictions on trace/segment attributes, as
|
|
4
|
+
well as error event/trace attributes.
|
|
5
|
+
|
|
6
|
+
* Fixes potential for `RangeError: Maximum call stack size exceeded` error on
|
|
7
|
+
Transaction/Trace end.
|
|
8
|
+
|
|
9
|
+
* Custom events no longer accept attributes with invalid types.
|
|
10
|
+
|
|
11
|
+
The only attribute types accepted by the backend are `boolean`, `string`, and
|
|
12
|
+
`number`; any attribute assigned to a custom event outside these types would be
|
|
13
|
+
dropped on ingest. The agent now filters these attributes out, and logs out a
|
|
14
|
+
helpful message detailing the issue.
|
|
15
|
+
|
|
16
|
+
### 5.6.1 (2019-03-11):
|
|
17
|
+
|
|
18
|
+
* Updated log message for not adding attributes and change the log level to debug.
|
|
19
|
+
|
|
20
|
+
* Fixed an issue where exclusive time would be improperly calculated in some cases.
|
|
21
|
+
|
|
22
|
+
### 5.6.0 (2019-03-04):
|
|
23
|
+
|
|
24
|
+
* Added `product` attribute to existing datastore instrumentations.
|
|
25
|
+
|
|
26
|
+
* Added `db.collection` to datastore span event attributes.
|
|
27
|
+
|
|
28
|
+
* `trusted_account_key`, `account_id`, and `primary_application_id` may now be
|
|
29
|
+
configured via a configuration file while in serverless mode.
|
|
30
|
+
|
|
31
|
+
* Fixed a bug where data belonging to distributed traces starting in the Node.js
|
|
32
|
+
agent would be prioritized over data produced from traces starting in other
|
|
33
|
+
language agents.
|
|
34
|
+
|
|
35
|
+
Previously, the agent would use the same random number for both the transaction
|
|
36
|
+
priority (used for data sampling) and the Distributed Tracing trace sampling
|
|
37
|
+
decision (whether to create DT data for a given transaction). This random number
|
|
38
|
+
reuse resulted in a bias that caused data from distributed traces started in the
|
|
39
|
+
Node.js agent to be prioritized above data that belongs to distributed traces
|
|
40
|
+
started in other language agents. The agent now makes individual rolls for each
|
|
41
|
+
of these quantities (i.e. the transaction priority and trace sampling decision),
|
|
42
|
+
eliminating the bias.
|
|
43
|
+
|
|
44
|
+
* Optimized exclusive time duration calculator.
|
|
45
|
+
|
|
46
|
+
Previously, the agent would spend a lot of time sorting redundant arrays while
|
|
47
|
+
calculating the exclusive time for the segments of a trace. This has been
|
|
48
|
+
refactored into a single postorder traversal over the tree which will calculate
|
|
49
|
+
the exclusive time for all segments in the subtree rooted at a given segment.
|
|
50
|
+
|
|
51
|
+
* Prevent a split on undefined location under certain conditions in Memcached.
|
|
52
|
+
|
|
53
|
+
Special thanks to Ben Wolfe (@bwolfe) for this fix!
|
|
54
|
+
|
|
55
|
+
### 5.4.0 (2019-02-19):
|
|
56
|
+
|
|
57
|
+
* Fixed issue where `shim.createSegment()` could result in modifying the parent
|
|
58
|
+
when opaque.
|
|
59
|
+
|
|
60
|
+
* Fixed issue where `http-outbound` would modify parent segments when parent is
|
|
61
|
+
opaque.
|
|
62
|
+
|
|
63
|
+
* Moved processing of exclusive time attribute out of `toJSON` and into `finalize`
|
|
64
|
+
to only be calculated once.
|
|
65
|
+
|
|
66
|
+
Previously, serializing a segment would result in calculating and caching exclusive
|
|
67
|
+
time which could result in issues if serialized prior to ending.
|
|
68
|
+
|
|
69
|
+
* Added `SNS` to message shim library names.
|
|
70
|
+
|
|
71
|
+
* Added check for `collect_span_events` in config sent from the server on connect.
|
|
72
|
+
|
|
73
|
+
Collection of span events can be disabled from the server configuration, but not
|
|
74
|
+
enabled.
|
|
75
|
+
|
|
76
|
+
* Refactored `Segment#toJSON` to be more readable.
|
|
77
|
+
|
|
78
|
+
* Added a `try/catch` to config initialization to safely handle invalid setting
|
|
79
|
+
combinations.
|
|
80
|
+
|
|
81
|
+
When an error is caught the agent is marked as disabled, which ultimately returns
|
|
82
|
+
a stub API and keeps the process running.
|
|
83
|
+
|
|
84
|
+
* String truncation is now done using a binary search over the byte length of the
|
|
85
|
+
string.
|
|
86
|
+
|
|
87
|
+
Previously this truncation was done using a linear search for the proper byte
|
|
88
|
+
length.
|
|
89
|
+
|
|
90
|
+
* Optimized segment and span attribute filtering.
|
|
91
|
+
|
|
1
92
|
### 5.3.0 (2019-02-12):
|
|
2
93
|
|
|
3
94
|
* Added `span_events` and `transaction_segments` attribute destinations.
|
package/api.js
CHANGED
|
@@ -9,6 +9,7 @@ const hashes = require('./lib/util/hashes')
|
|
|
9
9
|
const properties = require('./lib/util/properties')
|
|
10
10
|
const stringify = require('json-stringify-safe')
|
|
11
11
|
const shimmer = require('./lib/shimmer')
|
|
12
|
+
const isValidType = require('./lib/util/attribute-types')
|
|
12
13
|
const TransactionShim = require('./lib/shim/transaction-shim')
|
|
13
14
|
const TransactionHandle = require('./lib/transaction/handle')
|
|
14
15
|
const AwsLambda = require('./lib/serverless/aws-lambda')
|
|
@@ -16,7 +17,6 @@ const AwsLambda = require('./lib/serverless/aws-lambda')
|
|
|
16
17
|
const ATTR_DEST = require('./lib/config/attribute-filter').DESTINATIONS
|
|
17
18
|
const MODULE_TYPE = require('./lib/shim/constants').MODULE_TYPE
|
|
18
19
|
const NAMES = require('./lib/metrics/names')
|
|
19
|
-
|
|
20
20
|
/*
|
|
21
21
|
*
|
|
22
22
|
* CONSTANTS
|
|
@@ -365,7 +365,13 @@ API.prototype.noticeError = function noticeError(error, customAttributes) {
|
|
|
365
365
|
}
|
|
366
366
|
const transaction = this.agent.tracer.getTransaction()
|
|
367
367
|
|
|
368
|
-
|
|
368
|
+
// Filter all object type valued attributes out
|
|
369
|
+
let filteredAttributes = customAttributes
|
|
370
|
+
if (customAttributes) {
|
|
371
|
+
filteredAttributes = _filterAttributes(customAttributes, 'noticeError')
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
this.agent.errors.addUserError(transaction, error, filteredAttributes)
|
|
369
375
|
}
|
|
370
376
|
|
|
371
377
|
/**
|
|
@@ -1067,6 +1073,9 @@ API.prototype.recordCustomEvent = function recordCustomEvent(eventType, attribut
|
|
|
1067
1073
|
return
|
|
1068
1074
|
}
|
|
1069
1075
|
|
|
1076
|
+
// Filter all object type valued attributes out
|
|
1077
|
+
const filteredAttributes = _filterAttributes(attributes, `${eventType} custom event`)
|
|
1078
|
+
|
|
1070
1079
|
var instrinics = {
|
|
1071
1080
|
type: eventType,
|
|
1072
1081
|
timestamp: Date.now()
|
|
@@ -1074,7 +1083,7 @@ API.prototype.recordCustomEvent = function recordCustomEvent(eventType, attribut
|
|
|
1074
1083
|
|
|
1075
1084
|
var tx = this.agent.getTransaction()
|
|
1076
1085
|
var priority = tx && tx.priority || Math.random()
|
|
1077
|
-
this.agent.customEvents.add([instrinics,
|
|
1086
|
+
this.agent.customEvents.add([instrinics, filteredAttributes], priority)
|
|
1078
1087
|
}
|
|
1079
1088
|
|
|
1080
1089
|
/**
|
|
@@ -1390,4 +1399,19 @@ API.prototype.setLambdaHandler = function setLambdaHandler(handler) {
|
|
|
1390
1399
|
return this.awsLambda.patchLambdaHandler(handler)
|
|
1391
1400
|
}
|
|
1392
1401
|
|
|
1402
|
+
function _filterAttributes(attributes, name) {
|
|
1403
|
+
const filteredAttributes = Object.create(null)
|
|
1404
|
+
Object.keys(attributes).forEach((attributeKey) => {
|
|
1405
|
+
if (!isValidType(attributes[attributeKey])) {
|
|
1406
|
+
logger.info(
|
|
1407
|
+
`Omitting attribute ${attributeKey} from ${name} call, type must ` +
|
|
1408
|
+
'be boolean, number, or string'
|
|
1409
|
+
)
|
|
1410
|
+
return
|
|
1411
|
+
}
|
|
1412
|
+
filteredAttributes[attributeKey] = attributes[attributeKey]
|
|
1413
|
+
})
|
|
1414
|
+
return filteredAttributes
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1393
1417
|
module.exports = API
|
package/index.js
CHANGED
|
@@ -34,8 +34,8 @@ if (require.cache.__NR_cache) {
|
|
|
34
34
|
|
|
35
35
|
function initialize() {
|
|
36
36
|
logger.debug('Loading agent from %s', __dirname)
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
let agent = null
|
|
38
|
+
let message = null
|
|
39
39
|
|
|
40
40
|
try {
|
|
41
41
|
logger.debug(
|
|
@@ -45,8 +45,8 @@ function initialize() {
|
|
|
45
45
|
|
|
46
46
|
// TODO: Update this check when Node v6 is deprecated.
|
|
47
47
|
if (psemver.satisfies('<6.0.0')) {
|
|
48
|
-
message =
|
|
49
|
-
|
|
48
|
+
message = 'New Relic for Node.js requires a version of Node equal to or\n' +
|
|
49
|
+
'greater than 6.0.0. Not starting!'
|
|
50
50
|
|
|
51
51
|
logger.error(message)
|
|
52
52
|
throw new Error(message)
|
|
@@ -59,24 +59,24 @@ function initialize() {
|
|
|
59
59
|
)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
logger.debug(
|
|
63
|
-
logger.debug(
|
|
64
|
-
logger.debug(
|
|
62
|
+
logger.debug('Current working directory at module load is %s.', process.cwd())
|
|
63
|
+
logger.debug('Process title is %s.', process.title)
|
|
64
|
+
logger.debug('Application was invoked as %s.', process.argv.join(' '))
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
const config = require('./lib/config').getOrCreateInstance()
|
|
67
67
|
|
|
68
68
|
// Get the initialized logger as we likely have a bootstrap logger which
|
|
69
69
|
// just pipes to stdout.
|
|
70
70
|
logger = require('./lib/logger')
|
|
71
71
|
|
|
72
72
|
if (!config || !config.agent_enabled) {
|
|
73
|
-
logger.info(
|
|
73
|
+
logger.info('Module not enabled in configuration; not starting.')
|
|
74
74
|
} else {
|
|
75
75
|
agent = createAgent(config)
|
|
76
76
|
addStartupSupportabilities(agent)
|
|
77
77
|
}
|
|
78
78
|
} catch (error) {
|
|
79
|
-
message =
|
|
79
|
+
message = 'New Relic for Node.js was unable to bootstrap itself due to an error:'
|
|
80
80
|
logger.error(error, message)
|
|
81
81
|
|
|
82
82
|
/* eslint-disable no-console */
|
|
@@ -85,7 +85,7 @@ function initialize() {
|
|
|
85
85
|
/* eslint-enable no-console */
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
let API = null
|
|
89
89
|
if (agent) {
|
|
90
90
|
API = require('./api')
|
|
91
91
|
} else {
|
|
@@ -97,7 +97,7 @@ function initialize() {
|
|
|
97
97
|
// If we loaded an agent, record a startup time for the agent.
|
|
98
98
|
// NOTE: Metrics are recorded in seconds, so divide the value by 1000.
|
|
99
99
|
if (agent) {
|
|
100
|
-
|
|
100
|
+
const initDuration = (Date.now() - agentStart) / 1000
|
|
101
101
|
agent.recordSupportability('Nodejs/Application/Opening/Duration', preAgentTime)
|
|
102
102
|
agent.recordSupportability('Nodejs/Application/Initialization/Duration', initDuration)
|
|
103
103
|
agent.once('started', function timeAgentStart() {
|
|
@@ -117,9 +117,9 @@ function createAgent(config) {
|
|
|
117
117
|
* multiple times, with undefined results. New Relic's instrumentation
|
|
118
118
|
* can't be enabled or disabled without an application restart.
|
|
119
119
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
const Agent = require('./lib/agent')
|
|
121
|
+
const agent = new Agent(config)
|
|
122
|
+
const appNames = agent.config.applications()
|
|
123
123
|
|
|
124
124
|
if (config.logging.diagnostics) {
|
|
125
125
|
logger.warn(
|
|
@@ -128,7 +128,7 @@ function createAgent(config) {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
if (appNames.length < 1) {
|
|
131
|
-
|
|
131
|
+
const message =
|
|
132
132
|
'New Relic requires that you name this application!\n' +
|
|
133
133
|
'Set app_name in your newrelic.js file or set environment variable\n' +
|
|
134
134
|
'NEW_RELIC_APP_NAME. Not starting!'
|
|
@@ -136,17 +136,17 @@ function createAgent(config) {
|
|
|
136
136
|
throw new Error(message)
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
const shimmer = require('./lib/shimmer')
|
|
140
140
|
shimmer.patchModule(agent)
|
|
141
141
|
shimmer.bootstrapInstrumentation(agent)
|
|
142
142
|
|
|
143
143
|
// Check for already loaded modules and warn about them.
|
|
144
|
-
|
|
144
|
+
const uninstrumented = require('./lib/uninstrumented')
|
|
145
145
|
uninstrumented.check(shimmer.registeredInstrumentations)
|
|
146
146
|
|
|
147
147
|
agent.start(function afterStart(error) {
|
|
148
148
|
if (error) {
|
|
149
|
-
|
|
149
|
+
const errorMessage = 'New Relic for Node.js halted startup due to an error:'
|
|
150
150
|
logger.error(error, errorMessage)
|
|
151
151
|
|
|
152
152
|
/* eslint-disable no-console */
|
|
@@ -165,15 +165,15 @@ function createAgent(config) {
|
|
|
165
165
|
|
|
166
166
|
function addStartupSupportabilities(agent) {
|
|
167
167
|
// TODO: As new versions come out, make sure to update Angler metrics.
|
|
168
|
-
|
|
168
|
+
const nodeMajor = /^v?(\d+)/.exec(process.version)
|
|
169
169
|
agent.recordSupportability(
|
|
170
170
|
'Nodejs/Version/' + ((nodeMajor && nodeMajor[1]) || 'unknown')
|
|
171
171
|
)
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
for (
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
const configFlags = Object.keys(agent.config.feature_flag)
|
|
174
|
+
for (let i = 0; i < configFlags.length; ++i) {
|
|
175
|
+
const flag = configFlags[i]
|
|
176
|
+
const enabled = agent.config.feature_flag[flag]
|
|
177
177
|
|
|
178
178
|
if (enabled !== featureFlags[flag]) {
|
|
179
179
|
agent.recordSupportability(
|
package/lib/adaptive-sampler.js
CHANGED
|
@@ -8,7 +8,7 @@ class AdaptiveSampler {
|
|
|
8
8
|
this._samplingPeriod = 0
|
|
9
9
|
this._samplingTarget = opts.target
|
|
10
10
|
this._maxSamples = 2 * opts.target
|
|
11
|
-
this.
|
|
11
|
+
this._samplingThreshold = 0
|
|
12
12
|
this._resetCount = 0
|
|
13
13
|
this._resetInterval = null
|
|
14
14
|
|
|
@@ -24,8 +24,8 @@ class AdaptiveSampler {
|
|
|
24
24
|
return this._sampled
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
get
|
|
28
|
-
return this.
|
|
27
|
+
get samplingThreshold() {
|
|
28
|
+
return this._samplingThreshold
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
get samplingTarget() {
|
|
@@ -73,14 +73,13 @@ class AdaptiveSampler {
|
|
|
73
73
|
* Determines if an object should be sampled based on the object's priority and
|
|
74
74
|
* the number of objects sampled in this window.
|
|
75
75
|
*
|
|
76
|
-
* @param {
|
|
77
|
-
* @param {number} obj.priority - The priority of this object.
|
|
76
|
+
* @param {number} roll - The number to compare against the threshold
|
|
78
77
|
*
|
|
79
78
|
* @return {bool} True if the object should be sampled.
|
|
80
79
|
*/
|
|
81
|
-
shouldSample(
|
|
80
|
+
shouldSample(roll) {
|
|
82
81
|
++this._seen
|
|
83
|
-
if (
|
|
82
|
+
if (roll >= this._samplingThreshold) {
|
|
84
83
|
this._incrementSampled()
|
|
85
84
|
return true
|
|
86
85
|
}
|
|
@@ -100,7 +99,7 @@ class AdaptiveSampler {
|
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
/**
|
|
103
|
-
* Increments the sampled counter and adjusted the
|
|
102
|
+
* Increments the sampled counter and adjusted the sampling threshold to maintain
|
|
104
103
|
* a steady sample rate.
|
|
105
104
|
*/
|
|
106
105
|
_incrementSampled() {
|
|
@@ -126,7 +125,7 @@ class AdaptiveSampler {
|
|
|
126
125
|
_adjustStats(target) {
|
|
127
126
|
if (this._seen) {
|
|
128
127
|
const ratio = Math.min(target / this._seen, 1)
|
|
129
|
-
this.
|
|
128
|
+
this._samplingThreshold = 1 - ratio
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
}
|
package/lib/attributes.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const Config = require('./config')
|
|
3
4
|
const logger = require('./logger').child({component: 'attributes'})
|
|
5
|
+
const isValidType = require('./util/attribute-types')
|
|
4
6
|
const byteUtils = require('./util/byte-limit')
|
|
5
7
|
const properties = require('./util/properties')
|
|
6
8
|
|
|
@@ -9,9 +11,17 @@ const properties = require('./util/properties')
|
|
|
9
11
|
* @private
|
|
10
12
|
*/
|
|
11
13
|
class Attributes {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} scope
|
|
16
|
+
* The scope of the attributes this will collect. Must be `transaction` or
|
|
17
|
+
* `segment`.
|
|
18
|
+
*
|
|
19
|
+
* @param {number} [limit=Infinity]
|
|
20
|
+
* The maximum number of attributes to retrieve for each destination.
|
|
21
|
+
*/
|
|
22
|
+
constructor(scope, limit = Infinity) {
|
|
23
|
+
this.filter = makeFilter(scope)
|
|
24
|
+
this.limit = limit
|
|
15
25
|
this.attributes = Object.create(null)
|
|
16
26
|
}
|
|
17
27
|
|
|
@@ -21,7 +31,7 @@ class Attributes {
|
|
|
21
31
|
* @param {string} str - Object key name or value
|
|
22
32
|
*/
|
|
23
33
|
isValidLength(str) {
|
|
24
|
-
return byteUtils.isValidLength(str,
|
|
34
|
+
return typeof str === 'number' || byteUtils.isValidLength(str, 255)
|
|
25
35
|
}
|
|
26
36
|
|
|
27
37
|
/**
|
|
@@ -87,15 +97,20 @@ class Attributes {
|
|
|
87
97
|
* Adds given key-value pair to destination's agent attributes,
|
|
88
98
|
* if it passes filtering rules.
|
|
89
99
|
*
|
|
90
|
-
* @param {string} scope - Attribute scope ('transaction' or 'segment')
|
|
91
100
|
* @param {DESTINATIONS} destinations - The default destinations for this key.
|
|
92
101
|
* @param {string} key - The attribute name.
|
|
93
102
|
* @param {string} value - The attribute value.
|
|
94
|
-
* @param {boolean}
|
|
103
|
+
* @param {boolean} [truncateExempt=false] - Flag marking value exempt from truncation
|
|
95
104
|
*/
|
|
96
|
-
addAttribute(
|
|
105
|
+
addAttribute(destinations, key, value, truncateExempt = false) {
|
|
97
106
|
if (!isValidType(value)) {
|
|
98
|
-
return logger.
|
|
107
|
+
return logger.debug(
|
|
108
|
+
'Not adding attribute %s with %s value type. This is expected for undefined' +
|
|
109
|
+
'attributes and only an issue if an attribute is not expected to be undefined' +
|
|
110
|
+
'or not of the type expected.',
|
|
111
|
+
key,
|
|
112
|
+
typeof value
|
|
113
|
+
)
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
if (!this.isValidLength(key)) {
|
|
@@ -106,38 +121,42 @@ class Attributes {
|
|
|
106
121
|
}
|
|
107
122
|
|
|
108
123
|
// Only set the attribute if at least one destination passed
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
this._set(
|
|
124
|
+
const validDestinations = this.filter(destinations, key)
|
|
125
|
+
if (validDestinations) {
|
|
126
|
+
this._set(validDestinations, key, value, truncateExempt)
|
|
112
127
|
}
|
|
113
128
|
}
|
|
114
129
|
|
|
115
130
|
/**
|
|
116
131
|
* Passthrough method for adding multiple unknown attributes at once.
|
|
117
132
|
*
|
|
118
|
-
* @param {string} scope - 'transaction' or 'segment'
|
|
119
133
|
* @param {DESTINATIONS} destinations - The default destinations for these attributes.
|
|
120
134
|
* @param {object} attrs - The attributes to add.
|
|
121
135
|
*/
|
|
122
|
-
addAttributes(
|
|
136
|
+
addAttributes(destinations, attrs) {
|
|
123
137
|
for (let key in attrs) {
|
|
124
138
|
if (properties.hasOwn(attrs, key)) {
|
|
125
|
-
this.addAttribute(
|
|
139
|
+
this.addAttribute(destinations, key, attrs[key])
|
|
126
140
|
}
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
143
|
}
|
|
130
144
|
|
|
131
145
|
/**
|
|
132
|
-
*
|
|
133
|
-
* string, number, & boolean.
|
|
146
|
+
* Creates a filter function for the given scope.
|
|
134
147
|
*
|
|
135
|
-
* @param {
|
|
148
|
+
* @param {string} scope - The scope of the filter to make.
|
|
136
149
|
*
|
|
137
|
-
* @return {
|
|
150
|
+
* @return {function} A function that performs attribute filtering for the given
|
|
151
|
+
* scope.
|
|
138
152
|
*/
|
|
139
|
-
function
|
|
140
|
-
|
|
153
|
+
function makeFilter(scope) {
|
|
154
|
+
const {attributeFilter} = Config.getInstance()
|
|
155
|
+
if (scope === 'transaction') {
|
|
156
|
+
return (d, k) => attributeFilter.filterTransaction(d, k)
|
|
157
|
+
} else if (scope === 'segment') {
|
|
158
|
+
return (d, k) => attributeFilter.filterSegment(d, k)
|
|
159
|
+
}
|
|
141
160
|
}
|
|
142
161
|
|
|
143
162
|
module.exports = Attributes
|
package/lib/collector/facts.js
CHANGED
|
@@ -88,8 +88,13 @@ function getAllIPAddresses() {
|
|
|
88
88
|
const interfaceAddresses = interfaces[key].map(function getAddress(inter) {
|
|
89
89
|
return inter.address
|
|
90
90
|
})
|
|
91
|
-
|
|
91
|
+
|
|
92
|
+
for (let index = 0; index < interfaceAddresses.length; index++) {
|
|
93
|
+
const address = interfaceAddresses[index]
|
|
94
|
+
addresses.push(address)
|
|
95
|
+
}
|
|
92
96
|
}
|
|
97
|
+
|
|
93
98
|
return addresses
|
|
94
99
|
}, [])
|
|
95
100
|
}
|
|
@@ -169,7 +169,7 @@ RemoteMethod.prototype._safeRequest = function _safeRequest(options) {
|
|
|
169
169
|
const maxPayloadSize = this._config.max_payload_size_in_bytes
|
|
170
170
|
var level = 'trace'
|
|
171
171
|
|
|
172
|
-
if (!isValidLength(options.body, maxPayloadSize
|
|
172
|
+
if (!isValidLength(options.body, maxPayloadSize)) {
|
|
173
173
|
logger.warn(
|
|
174
174
|
'The payload size %d being sent to method %s exceeded the maximum size of %d',
|
|
175
175
|
Buffer.byteLength(options.body, 'utf8'),
|
|
@@ -40,11 +40,6 @@ const SEGMENT_SCOPE_DETAILS = [
|
|
|
40
40
|
|
|
41
41
|
const DESTINATION_DETAILS = [...TRANS_SCOPE_DETAILS, ...SEGMENT_SCOPE_DETAILS]
|
|
42
42
|
|
|
43
|
-
const SCOPES = {
|
|
44
|
-
segment: SEGMENT_SCOPE_DETAILS,
|
|
45
|
-
transaction: TRANS_SCOPE_DETAILS
|
|
46
|
-
}
|
|
47
|
-
|
|
48
43
|
module.exports = exports = AttributeFilter
|
|
49
44
|
exports.DESTINATIONS = DESTINATIONS
|
|
50
45
|
|
|
@@ -84,16 +79,53 @@ function AttributeFilter(config) {
|
|
|
84
79
|
this.update()
|
|
85
80
|
}
|
|
86
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Tests a given key against the global and destination transaction filters.
|
|
84
|
+
*
|
|
85
|
+
* @param {DESTINATIONS} destinations - The locations the attribute wants to be put.
|
|
86
|
+
* @param {string} key - The name of the attribute to test.
|
|
87
|
+
*
|
|
88
|
+
* @return {DESTINATIONS} The destinations the attribute should be put.
|
|
89
|
+
*/
|
|
90
|
+
AttributeFilter.prototype.filterTransaction = filterTransaction
|
|
91
|
+
function filterTransaction(destinations, key) {
|
|
92
|
+
return this._filter(TRANS_SCOPE_DETAILS, destinations, key)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Tests a given key against the global and destination segment filters.
|
|
97
|
+
*
|
|
98
|
+
* @param {DESTINATIONS} destinations - The locations the attribute wants to be put.
|
|
99
|
+
* @param {string} key - The name of the attribute to test.
|
|
100
|
+
*
|
|
101
|
+
* @return {DESTINATIONS} The destinations the attribute should be put.
|
|
102
|
+
*/
|
|
103
|
+
AttributeFilter.prototype.filterSegment = function filterSegment(destinations, key) {
|
|
104
|
+
return this._filter(SEGMENT_SCOPE_DETAILS, destinations, key)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Tests a given key against all global and destination filters.
|
|
109
|
+
*
|
|
110
|
+
* @param {DESTINATIONS} destinations - The locations the attribute wants to be put.
|
|
111
|
+
* @param {string} key - The name of the attribute to test.
|
|
112
|
+
*
|
|
113
|
+
* @return {DESTINATIONS} The destinations the attribute should be put.
|
|
114
|
+
*/
|
|
115
|
+
AttributeFilter.prototype.filterAll = function filterSegment(destinations, key) {
|
|
116
|
+
return this._filter(DESTINATION_DETAILS, destinations, key)
|
|
117
|
+
}
|
|
118
|
+
|
|
87
119
|
/**
|
|
88
120
|
* Tests a given key against the global and destination filters.
|
|
89
121
|
*
|
|
90
|
-
* @param {array}
|
|
91
|
-
* @param {DESTINATIONS}
|
|
92
|
-
* @param {string}
|
|
122
|
+
* @param {array} scope - The destination details for filtering.
|
|
123
|
+
* @param {DESTINATIONS} destinations - The locations the attribute wants to be put.
|
|
124
|
+
* @param {string} key - The name of the attribute to test.
|
|
93
125
|
*
|
|
94
126
|
* @return {DESTINATIONS} The destinations the attribute should be put.
|
|
95
127
|
*/
|
|
96
|
-
AttributeFilter.prototype.
|
|
128
|
+
AttributeFilter.prototype._filter = function _filter(scope, destinations, key) {
|
|
97
129
|
// This method could be easily memoized since for a given destination and key
|
|
98
130
|
// the result will always be the same until a configuration update happens. A
|
|
99
131
|
// given application will also have a controllable set of destinations and
|
|
@@ -104,15 +136,13 @@ AttributeFilter.prototype.filter = function test(scope, destinations, key) {
|
|
|
104
136
|
return DESTINATIONS.NONE
|
|
105
137
|
}
|
|
106
138
|
|
|
107
|
-
const scopeDetails = SCOPES[scope] || DESTINATION_DETAILS
|
|
108
|
-
|
|
109
139
|
// These are lazy computed to avoid calculating them for cached results.
|
|
110
140
|
var globalInclude = null
|
|
111
141
|
var globalExclude = null
|
|
112
142
|
|
|
113
143
|
// Iterate over each desination and see if the rules apply.
|
|
114
|
-
for (var i = 0; i <
|
|
115
|
-
var dest =
|
|
144
|
+
for (var i = 0; i < scope.length; ++i) {
|
|
145
|
+
var dest = scope[i]
|
|
116
146
|
var destId = dest.id
|
|
117
147
|
var destName = dest.name
|
|
118
148
|
if (!(this._enabledDestinations & destId)) {
|
package/lib/config/default.js
CHANGED
|
@@ -88,6 +88,10 @@ exports.config = () => ({
|
|
|
88
88
|
* @env NEW_RELIC_PROXY_PASS
|
|
89
89
|
*/
|
|
90
90
|
proxy_pass: '',
|
|
91
|
+
// Serverless DT config defaults
|
|
92
|
+
trusted_account_key: null,
|
|
93
|
+
primary_application_id: null,
|
|
94
|
+
account_id: null,
|
|
91
95
|
/**
|
|
92
96
|
* Custom SSL certificates
|
|
93
97
|
*
|
|
@@ -881,5 +885,5 @@ exports.config = () => ({
|
|
|
881
885
|
* loop data.
|
|
882
886
|
*/
|
|
883
887
|
native_metrics: {enabled: true}
|
|
884
|
-
}
|
|
888
|
+
},
|
|
885
889
|
})
|
package/lib/config/env.js
CHANGED
|
@@ -137,7 +137,7 @@ const ENV_MAPPING = {
|
|
|
137
137
|
enabled: 'NEW_RELIC_SERVERLESS_MODE_ENABLED'
|
|
138
138
|
},
|
|
139
139
|
trusted_account_key: 'NEW_RELIC_TRUSTED_ACCOUNT_KEY',
|
|
140
|
-
|
|
140
|
+
primary_application_id: 'NEW_RELIC_PRIMARY_APPLICATION_ID',
|
|
141
141
|
account_id: 'NEW_RELIC_ACCOUNT_ID'
|
|
142
142
|
}
|
|
143
143
|
|