newrelic 13.5.0 → 13.6.1
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 +51 -0
- package/api.js +3 -3
- package/lib/agent.js +2 -2
- package/lib/aggregators/log-aggregator.js +2 -2
- package/lib/collector/api.js +6 -6
- package/lib/collector/remote-method.js +1 -1
- package/lib/config/attribute-filter.js +7 -7
- package/lib/config/default.js +5 -5
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +28 -26
- package/lib/config/merge-server-config.js +6 -6
- package/lib/core-instrumentation.js +4 -0
- package/lib/db/query-parsers/elasticsearch.js +5 -4
- package/lib/db/query-parsers/sql.js +1 -1
- package/lib/environment.js +16 -16
- package/lib/errors/index.js +1 -1
- package/lib/harvester.js +7 -5
- package/lib/header-attributes.js +3 -3
- package/lib/instrumentation/@google/genai.js +6 -9
- package/lib/instrumentation/aws-sdk/v3/bedrock.js +11 -9
- package/lib/instrumentation/bunyan.js +1 -5
- package/lib/instrumentation/core/child_process.js +4 -4
- package/lib/instrumentation/core/fs.js +2 -2
- package/lib/instrumentation/core/http2.js +266 -0
- package/lib/instrumentation/core/timers.js +4 -4
- package/lib/instrumentation/fastify.js +1 -1
- package/lib/instrumentation/grpc-js/grpc.js +7 -7
- package/lib/instrumentation/koa/route-instrumentation.js +16 -18
- package/lib/instrumentation/langchain/runnable.js +2 -2
- package/lib/instrumentation/langchain/vectorstore.js +3 -2
- package/lib/instrumentation/when/index.js +5 -5
- package/lib/instrumentation/winston.js +1 -1
- package/lib/instrumentation-tracker.js +2 -2
- package/lib/instrumentations.js +0 -1
- package/lib/llm-events/aws-bedrock/bedrock-response.js +9 -0
- package/lib/llm-events/aws-bedrock/chat-completion-message.js +32 -4
- package/lib/llm-events/aws-bedrock/chat-completion-summary.js +30 -1
- package/lib/llm-events/aws-bedrock/embedding.js +37 -4
- package/lib/llm-events/aws-bedrock/stream-handler.js +22 -0
- package/lib/llm-events/aws-bedrock/utils.js +59 -1
- package/lib/llm-events/google-genai/chat-completion-message.js +33 -5
- package/lib/llm-events/google-genai/chat-completion-summary.js +33 -0
- package/lib/llm-events/google-genai/embedding.js +34 -4
- package/lib/llm-events/google-genai/utils.js +32 -0
- package/lib/llm-events/openai/chat-completion-message.js +33 -6
- package/lib/llm-events/openai/chat-completion-summary.js +36 -0
- package/lib/llm-events/openai/embedding.js +34 -4
- package/lib/llm-events/openai/utils.js +34 -0
- package/lib/llm-events/utils.js +110 -0
- package/lib/metrics/index.js +7 -7
- package/lib/metrics/normalizer/tx_segment.js +26 -28
- package/lib/metrics/normalizer.js +9 -7
- package/lib/metrics/recorders/distributed-trace.js +2 -2
- package/lib/otel/traces/rules.js +2 -2
- package/lib/serverless/aws-lambda.js +7 -7
- package/lib/shim/datastore-shim.js +8 -8
- package/lib/shim/message-shim/index.js +8 -8
- package/lib/shim/message-shim/subscribe-consume.js +12 -10
- package/lib/shim/promise-shim.js +3 -3
- package/lib/shim/shim.js +11 -9
- package/lib/shim/transaction-shim.js +7 -7
- package/lib/shim/webframework-shim/index.js +8 -9
- package/lib/shimmer.js +19 -26
- package/lib/stats/apdex.js +1 -1
- package/lib/subscriber-configs.js +1 -0
- package/lib/subscribers/dc-base.js +6 -4
- package/lib/subscribers/express/config.js +102 -0
- package/lib/subscribers/express/param.js +22 -0
- package/lib/subscribers/express/render.js +28 -0
- package/lib/subscribers/express/route.js +55 -0
- package/lib/subscribers/express/router-param.js +24 -0
- package/lib/subscribers/express/router-route.js +24 -0
- package/lib/subscribers/express/router-use.js +24 -0
- package/lib/subscribers/express/use.js +46 -0
- package/lib/subscribers/fastify/add-hook.js +5 -6
- package/lib/subscribers/fastify/decorate.js +6 -8
- package/lib/subscribers/fastify/index.js +3 -2
- package/lib/subscribers/ioredis/config.js +3 -3
- package/lib/subscribers/ioredis/index.js +24 -1
- package/lib/subscribers/middleware-wrapper.js +278 -0
- package/lib/subscribers/middleware.js +20 -0
- package/lib/subscribers/openai/base.js +5 -6
- package/lib/subscribers/openai/utils.js +5 -4
- package/lib/system-metrics-sampler.js +5 -5
- package/lib/transaction/index.js +7 -7
- package/lib/transaction/name-state.js +4 -4
- package/lib/transaction/trace/aggregator.js +1 -1
- package/lib/transaction/trace/index.js +3 -1
- package/lib/transaction/trace/segment.js +2 -2
- package/lib/uninstrumented.js +4 -4
- package/lib/util/hashes.js +4 -4
- package/lib/util/label-parser.js +7 -7
- package/lib/util/logger.js +3 -3
- package/lib/util/process-version.js +1 -1
- package/lib/utilization/docker-info.js +1 -1
- package/lib/utilization/index.js +2 -2
- package/newrelic.js +1 -1
- package/package.json +1 -1
- package/lib/instrumentation/express.js +0 -176
- package/lib/subscribers/fastify/common.js +0 -121
package/NEWS.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
### v13.6.1 (2025-10-28)
|
|
2
|
+
|
|
3
|
+
#### Bug fixes
|
|
4
|
+
|
|
5
|
+
* Updated middleware wrapper to not wrap handler if it is not a function ([#3469](https://github.com/newrelic/node-newrelic/pull/3469)) ([c702689](https://github.com/newrelic/node-newrelic/commit/c702689a6e73756f6b3ad39706a33874fbd6da73))
|
|
6
|
+
|
|
7
|
+
#### Documentation
|
|
8
|
+
|
|
9
|
+
* Updated compatibility report ([#3466](https://github.com/newrelic/node-newrelic/pull/3466)) ([5853657](https://github.com/newrelic/node-newrelic/commit/5853657a63dc75481fc6598c10afd208391f525b))
|
|
10
|
+
|
|
11
|
+
### v13.6.0 (2025-10-27)
|
|
12
|
+
|
|
13
|
+
#### Features
|
|
14
|
+
|
|
15
|
+
* Added instrumentation for http2 client methods ([#3284](https://github.com/newrelic/node-newrelic/pull/3284)) ([bda7aea](https://github.com/newrelic/node-newrelic/commit/bda7aeaac16ce9f54bd28de72aa7465be96cd157))
|
|
16
|
+
|
|
17
|
+
#### Bug fixes
|
|
18
|
+
|
|
19
|
+
* Updated `ioredis` instrumentation to handle breakage of errors when using `.pipeline`. ([#3457](https://github.com/newrelic/node-newrelic/pull/3457)) ([49f4d93](https://github.com/newrelic/node-newrelic/commit/49f4d93a59045f35406dfdbd3248dca0652727d6))
|
|
20
|
+
* Updated `openai` `instrumentStream` function to handle empty chunk when `include_usage` is set ([#3427](https://github.com/newrelic/node-newrelic/pull/3427)) ([f804940](https://github.com/newrelic/node-newrelic/commit/f8049405003f0811450f75468e0bddfb1f05ec2b))
|
|
21
|
+
|
|
22
|
+
#### Code refactoring
|
|
23
|
+
|
|
24
|
+
* Update `express` instrumentation to subscribe to events emitted ([#3424](https://github.com/newrelic/node-newrelic/pull/3424)) ([bbf3d01](https://github.com/newrelic/node-newrelic/commit/bbf3d010bc402953e53cae5200af6bfb55a6446d))
|
|
25
|
+
* Updated instances in instrumentation of `Array.forEach` for a more performant for...of or for index loop ([#3463](https://github.com/newrelic/node-newrelic/pull/3463)) ([99484ce](https://github.com/newrelic/node-newrelic/commit/99484ce0e7a963fbbc3cbc22f4956ce19e5eecc2))
|
|
26
|
+
* Updated instances of `Array.forEach` for a more performant for...of or for index loop ([#3440](https://github.com/newrelic/node-newrelic/pull/3440)) ([48c37bf](https://github.com/newrelic/node-newrelic/commit/48c37bf7f85291553666d4512ca995b6a5b136a2))
|
|
27
|
+
* Updated token calculation for `aws-bedrock` LLM Events ([#3445](https://github.com/newrelic/node-newrelic/pull/3445)) ([9450181](https://github.com/newrelic/node-newrelic/commit/945018171da713487a0b5b674e68bdbb211e655e))
|
|
28
|
+
* Updated token calculation for `google-genai` LLM Events ([#3431](https://github.com/newrelic/node-newrelic/pull/3431)) ([41d32be](https://github.com/newrelic/node-newrelic/commit/41d32befe1d9c3201b62253a5de76c918d98a025))
|
|
29
|
+
* Updated token calculation for `openai` LLM Events ([#3430](https://github.com/newrelic/node-newrelic/pull/3430)) ([b8678cc](https://github.com/newrelic/node-newrelic/commit/b8678cc92bb986eae7efec4b516f66406307e841))
|
|
30
|
+
|
|
31
|
+
#### Documentation
|
|
32
|
+
|
|
33
|
+
* Updated compatibility report ([#3459](https://github.com/newrelic/node-newrelic/pull/3459)) ([f253b97](https://github.com/newrelic/node-newrelic/commit/f253b97c039caa9e9110055d93e0c32e2d6911a8))
|
|
34
|
+
|
|
35
|
+
#### Miscellaneous chores
|
|
36
|
+
|
|
37
|
+
* Update release workflows ([#3444](https://github.com/newrelic/node-newrelic/pull/3444)) ([d1ec158](https://github.com/newrelic/node-newrelic/commit/d1ec158f46d034160b665f8b0785c020ba39b820))
|
|
38
|
+
|
|
39
|
+
#### Tests
|
|
40
|
+
|
|
41
|
+
* Added a `randomString` helper to agent_helper and use it in ioredis to avoid flappy tests, also updated local instances of random strings in kafka, elasticsearch and opensearch tests ([#3462](https://github.com/newrelic/node-newrelic/pull/3462)) ([4deb6d8](https://github.com/newrelic/node-newrelic/commit/4deb6d80d9daa7fd9d4c077a5cc52f358ed44e61))
|
|
42
|
+
* Fixed conflict between ioredis and ioredis-esm by running `flushdb` instead of `flushall` to avoid index getting removed mid test ([#3464](https://github.com/newrelic/node-newrelic/pull/3464)) ([5e3f0a8](https://github.com/newrelic/node-newrelic/commit/5e3f0a81bfcf8bc8cf04559f29d3a76c1262bcc7))
|
|
43
|
+
* Fixed express async error test to purposely misspell a method to emit a crash ([#3435](https://github.com/newrelic/node-newrelic/pull/3435)) ([ff9f064](https://github.com/newrelic/node-newrelic/commit/ff9f0646c4fc23e367c1e190eb8091423c690103))
|
|
44
|
+
* Moved aws-sdk-v3 common.js requirement of semver ([#3461](https://github.com/newrelic/node-newrelic/pull/3461)) ([6a380ef](https://github.com/newrelic/node-newrelic/commit/6a380ef580268be131417587a2dda5adf3545e68))
|
|
45
|
+
* Pinned Next.js tests to <16.0.0 ([#3446](https://github.com/newrelic/node-newrelic/pull/3446)) ([10787a1](https://github.com/newrelic/node-newrelic/commit/10787a1f4e325b7321173ee5b2fab0809af5e8d1))
|
|
46
|
+
* Updated minimum tested version of `@langchain/core` to 1.0.0 ([#3437](https://github.com/newrelic/node-newrelic/pull/3437)) ([b61f67a](https://github.com/newrelic/node-newrelic/commit/b61f67a4c6d59f0b2a49e0de93a6d38e56d214fd))
|
|
47
|
+
|
|
1
48
|
### v13.5.0 (2025-10-14)
|
|
2
49
|
|
|
3
50
|
#### Code refactoring
|
|
@@ -7960,3 +8007,7 @@ Special thanks to Ryan Copley (@RyanCopley) for the contribution.
|
|
|
7960
8007
|
|
|
7961
8008
|
|
|
7962
8009
|
|
|
8010
|
+
|
|
8011
|
+
|
|
8012
|
+
|
|
8013
|
+
|
package/api.js
CHANGED
|
@@ -1813,16 +1813,16 @@ API.prototype.setUserID = function setUserID(id) {
|
|
|
1813
1813
|
*/
|
|
1814
1814
|
function _filterAttributes(attributes, name) {
|
|
1815
1815
|
const filteredAttributes = Object.create(null)
|
|
1816
|
-
Object.keys(attributes)
|
|
1816
|
+
for (const attributeKey of Object.keys(attributes)) {
|
|
1817
1817
|
if (!isValidType(attributes[attributeKey])) {
|
|
1818
1818
|
logger.info(
|
|
1819
1819
|
`Omitting attribute ${attributeKey} from ${name} call, type must ` +
|
|
1820
1820
|
'be boolean, number, or string'
|
|
1821
1821
|
)
|
|
1822
|
-
|
|
1822
|
+
continue
|
|
1823
1823
|
}
|
|
1824
1824
|
filteredAttributes[attributeKey] = attributes[attributeKey]
|
|
1825
|
-
}
|
|
1825
|
+
}
|
|
1826
1826
|
return filteredAttributes
|
|
1827
1827
|
}
|
|
1828
1828
|
|
package/lib/agent.js
CHANGED
|
@@ -444,7 +444,7 @@ Agent.prototype._scheduleHarvests = function _scheduleHarvests(shouldImmediately
|
|
|
444
444
|
|
|
445
445
|
const agent = this
|
|
446
446
|
|
|
447
|
-
// For data collection that streams immediately,
|
|
447
|
+
// For data collection that streams immediately, don't delay capture/sending until
|
|
448
448
|
// the harvest of everything else has completed.
|
|
449
449
|
agent.startStreaming()
|
|
450
450
|
|
|
@@ -564,7 +564,7 @@ Agent.prototype._resetCustomEvents = function resetCustomEvents() {
|
|
|
564
564
|
* @fires Agent#harvestFinished
|
|
565
565
|
*/
|
|
566
566
|
Agent.prototype.harvestSync = function harvestSync() {
|
|
567
|
-
logger.trace('
|
|
567
|
+
logger.trace('Preparing to harvest.')
|
|
568
568
|
|
|
569
569
|
if (!this.collector.isConnected()) {
|
|
570
570
|
throw new Error('Sync harvest not connected/enabled!')
|
package/lib/collector/api.js
CHANGED
|
@@ -63,15 +63,15 @@ const AGENT_RUN_BEHAVIOR = CollectorResponse.AGENT_RUN_BEHAVIOR
|
|
|
63
63
|
function dumpErrors(errors, name) {
|
|
64
64
|
let index = 1
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
for (const error of errors) {
|
|
67
67
|
logger.trace(error, 'Error %s during %s:', index++, name)
|
|
68
68
|
|
|
69
69
|
if (error.laterErrors) {
|
|
70
|
-
error.laterErrors
|
|
70
|
+
for (const laterError of error.laterErrors) {
|
|
71
71
|
logger.trace(laterError, 'Error %s during %s:', index++, name)
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
73
|
}
|
|
74
|
-
}
|
|
74
|
+
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
@@ -421,9 +421,9 @@ CollectorAPI.prototype._onConnect = function _onConnect(callback, error, res) {
|
|
|
421
421
|
|
|
422
422
|
// Log "Reporting to..." message from connect response.
|
|
423
423
|
if (config.messages) {
|
|
424
|
-
config.messages
|
|
424
|
+
for (const element of config.messages) {
|
|
425
425
|
logger.info(element.message)
|
|
426
|
-
}
|
|
426
|
+
}
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
// Store request headers for future collector requests if they're present
|
|
@@ -260,7 +260,7 @@ RemoteMethod.prototype._safeRequest = function _safeRequest(options) {
|
|
|
260
260
|
level = 'info'
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
-
// check if trace is enabled or audit log(aka info in this case) before
|
|
263
|
+
// check if trace is enabled or audit log(aka info in this case) before attempting
|
|
264
264
|
// to get the body length or parse the path with redacted key
|
|
265
265
|
if (logger.traceEnabled() || level === 'info') {
|
|
266
266
|
const logBody = Buffer.isBuffer(options.body) ? 'Buffer ' + options.body.length : options.body
|
|
@@ -70,12 +70,12 @@ function AttributeFilter(config) {
|
|
|
70
70
|
this._rules.global = Object.create(null)
|
|
71
71
|
|
|
72
72
|
// And all the destination rules.
|
|
73
|
-
|
|
73
|
+
for (const dest of DESTINATION_DETAILS) {
|
|
74
74
|
config.on(dest.name + '.attributes.enabled', updater)
|
|
75
75
|
config.on(dest.name + '.attributes.include', updater)
|
|
76
76
|
config.on(dest.name + '.attributes.exclude', updater)
|
|
77
77
|
this._rules[dest.name] = Object.create(null)
|
|
78
|
-
}
|
|
78
|
+
}
|
|
79
79
|
|
|
80
80
|
// Now pull in all the rules.
|
|
81
81
|
this.update()
|
|
@@ -184,10 +184,10 @@ AttributeFilter.prototype.update = function update() {
|
|
|
184
184
|
this._cachedCount = 0
|
|
185
185
|
|
|
186
186
|
// And all the destination rules.
|
|
187
|
-
|
|
187
|
+
for (const dest of DESTINATION_DETAILS) {
|
|
188
188
|
const name = dest.name
|
|
189
189
|
if (!this.config[name].attributes.enabled) {
|
|
190
|
-
|
|
190
|
+
continue
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
this._enabledDestinations |= dest.id
|
|
@@ -196,7 +196,7 @@ AttributeFilter.prototype.update = function update() {
|
|
|
196
196
|
)
|
|
197
197
|
this._rules[name].exclude = _importRules(this.config[name].attributes.exclude)
|
|
198
198
|
this._cache[name] = Object.create(null)
|
|
199
|
-
}
|
|
199
|
+
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
@@ -291,13 +291,13 @@ function _importRules(rules) {
|
|
|
291
291
|
}
|
|
292
292
|
const exactRules = []
|
|
293
293
|
const wildcardRules = []
|
|
294
|
-
|
|
294
|
+
for (const rule of rules) {
|
|
295
295
|
if (rule[rule.length - 1] === '*') {
|
|
296
296
|
wildcardRules.push(rule)
|
|
297
297
|
} else {
|
|
298
298
|
exactRules.push(rule)
|
|
299
299
|
}
|
|
300
|
-
}
|
|
300
|
+
}
|
|
301
301
|
|
|
302
302
|
if (exactRules.length) {
|
|
303
303
|
out.exact = new RegExp('^' + _convertRulesToRegex(exactRules) + '$')
|
package/lib/config/default.js
CHANGED
|
@@ -323,7 +323,7 @@ defaultConfig.definition = () => {
|
|
|
323
323
|
*/
|
|
324
324
|
diagnostics: {
|
|
325
325
|
formatter: boolean,
|
|
326
|
-
|
|
326
|
+
default: false
|
|
327
327
|
}
|
|
328
328
|
},
|
|
329
329
|
audit_log: {
|
|
@@ -1145,7 +1145,7 @@ defaultConfig.definition = () => {
|
|
|
1145
1145
|
/**
|
|
1146
1146
|
* Controls whether the agent will generate spans for in-process actions.
|
|
1147
1147
|
* When disabled, this will only create spans for entry and exit spans.
|
|
1148
|
-
* entry spans - initial actions for web servers and
|
|
1148
|
+
* entry spans - initial actions for web servers and message queue consumption.
|
|
1149
1149
|
* exit spans - all outgoing calls to external services(external and database calls)
|
|
1150
1150
|
*/
|
|
1151
1151
|
in_process_spans: {
|
|
@@ -1399,7 +1399,7 @@ defaultConfig.definition = () => {
|
|
|
1399
1399
|
/**
|
|
1400
1400
|
* Obfuscates URL parameters
|
|
1401
1401
|
* for outgoing and incoming requests
|
|
1402
|
-
* for
|
|
1402
|
+
* for distributed tracing attributes - both transaction and span attributes
|
|
1403
1403
|
* for transaction trace transaction details
|
|
1404
1404
|
*/
|
|
1405
1405
|
url_obfuscation: {
|
|
@@ -1429,7 +1429,7 @@ defaultConfig.definition = () => {
|
|
|
1429
1429
|
|
|
1430
1430
|
/**
|
|
1431
1431
|
* A string containing a replacement value for URL parameters
|
|
1432
|
-
* can contain
|
|
1432
|
+
* can contain references to capture groups in the pattern
|
|
1433
1433
|
*/
|
|
1434
1434
|
replacement: {
|
|
1435
1435
|
default: ''
|
|
@@ -1499,7 +1499,7 @@ defaultConfig.definition = () => {
|
|
|
1499
1499
|
},
|
|
1500
1500
|
|
|
1501
1501
|
/**
|
|
1502
|
-
* Unique test identifier when
|
|
1502
|
+
* Unique test identifier when running IAST with CI/CD
|
|
1503
1503
|
*/
|
|
1504
1504
|
iast_test_identifier: '',
|
|
1505
1505
|
|
package/lib/config/hsm.js
CHANGED
|
@@ -71,7 +71,7 @@ const REDACT_BEFORE_SEND = new Set([
|
|
|
71
71
|
'certificates' // should be public but in case user mistake and also these are huge
|
|
72
72
|
])
|
|
73
73
|
|
|
74
|
-
// process.domain needs to be stripped
|
|
74
|
+
// process.domain needs to be stripped before sending
|
|
75
75
|
const REMOVE_BEFORE_SEND = new Set(['domain'])
|
|
76
76
|
|
|
77
77
|
exports.HIGH_SECURITY_SETTINGS = HIGH_SECURITY_SETTINGS
|
package/lib/config/index.js
CHANGED
|
@@ -277,9 +277,9 @@ Config.prototype.onConnect = function onConnect(json, recursion) {
|
|
|
277
277
|
return
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
Object.keys(json)
|
|
280
|
+
for (const key of Object.keys(json)) {
|
|
281
281
|
this._fromServer(json, key)
|
|
282
|
-
}
|
|
282
|
+
}
|
|
283
283
|
|
|
284
284
|
this._warnDeprecations()
|
|
285
285
|
|
|
@@ -652,11 +652,11 @@ Config.prototype._alwaysUpdateIfChanged = function _alwaysUpdateIfChanged(json,
|
|
|
652
652
|
const value = json[key]
|
|
653
653
|
if (value != null && this[key] !== value) {
|
|
654
654
|
if (Array.isArray(value) && Array.isArray(this[key])) {
|
|
655
|
-
|
|
655
|
+
for (const element of value) {
|
|
656
656
|
if (this[key].indexOf(element) === -1) {
|
|
657
657
|
this[key].push(element)
|
|
658
658
|
}
|
|
659
|
-
}
|
|
659
|
+
}
|
|
660
660
|
} else {
|
|
661
661
|
this[key] = value
|
|
662
662
|
}
|
|
@@ -703,7 +703,7 @@ function _validateThenUpdateStatusCodes(remote, local, remoteKey, localKey) {
|
|
|
703
703
|
}
|
|
704
704
|
|
|
705
705
|
let valid = true
|
|
706
|
-
|
|
706
|
+
for (const thingToTest of valueToTest) {
|
|
707
707
|
if (!(typeof thingToTest === 'string' || typeof thingToTest === 'number')) {
|
|
708
708
|
logger.warn(
|
|
709
709
|
'Saw SSC (ignore|expect)_status_code that is not a number or string,' +
|
|
@@ -712,7 +712,7 @@ function _validateThenUpdateStatusCodes(remote, local, remoteKey, localKey) {
|
|
|
712
712
|
)
|
|
713
713
|
valid = false
|
|
714
714
|
}
|
|
715
|
-
}
|
|
715
|
+
}
|
|
716
716
|
if (!valid) {
|
|
717
717
|
return
|
|
718
718
|
}
|
|
@@ -747,7 +747,7 @@ function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
|
|
|
747
747
|
}
|
|
748
748
|
|
|
749
749
|
let valid = true
|
|
750
|
-
Object.keys(valueToTest)
|
|
750
|
+
for (const key of Object.keys(valueToTest)) {
|
|
751
751
|
const thingToTest = valueToTest[key]
|
|
752
752
|
if (typeof thingToTest !== 'string') {
|
|
753
753
|
logger.warn(
|
|
@@ -756,7 +756,7 @@ function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
|
|
|
756
756
|
)
|
|
757
757
|
valid = false
|
|
758
758
|
}
|
|
759
|
-
}
|
|
759
|
+
}
|
|
760
760
|
if (!valid) {
|
|
761
761
|
return
|
|
762
762
|
}
|
|
@@ -801,13 +801,13 @@ function _validateThenUpdateErrorMessages(remote, local, remoteKey, localKey) {
|
|
|
801
801
|
}
|
|
802
802
|
|
|
803
803
|
let valid = true
|
|
804
|
-
Object.keys(valueToTest)
|
|
804
|
+
for (const key of Object.keys(valueToTest)) {
|
|
805
805
|
const arrayToTest = valueToTest[key]
|
|
806
806
|
if (!Array.isArray(arrayToTest)) {
|
|
807
807
|
logger.warn('Saw SSC message array that is not an array, will not merge: %s', arrayToTest)
|
|
808
808
|
valid = false
|
|
809
809
|
}
|
|
810
|
-
}
|
|
810
|
+
}
|
|
811
811
|
if (!valid) {
|
|
812
812
|
return
|
|
813
813
|
}
|
|
@@ -1058,15 +1058,15 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
1058
1058
|
internal = this
|
|
1059
1059
|
}
|
|
1060
1060
|
|
|
1061
|
-
Object.keys(external)
|
|
1061
|
+
for (const key of Object.keys(external)) {
|
|
1062
1062
|
// if it's not in the defaults, it doesn't exist
|
|
1063
1063
|
if (!arbitrary && !(key in internal)) {
|
|
1064
|
-
|
|
1064
|
+
continue
|
|
1065
1065
|
}
|
|
1066
1066
|
|
|
1067
1067
|
if (key === 'ssl' && !isTruthular(external.ssl)) {
|
|
1068
1068
|
logger.warn(SSL_WARNING)
|
|
1069
|
-
|
|
1069
|
+
continue
|
|
1070
1070
|
}
|
|
1071
1071
|
|
|
1072
1072
|
let node = null
|
|
@@ -1074,7 +1074,7 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
1074
1074
|
node = external[key]
|
|
1075
1075
|
} catch {
|
|
1076
1076
|
logger.warn('Error thrown on access of user config for key: %s', key)
|
|
1077
|
-
|
|
1077
|
+
continue
|
|
1078
1078
|
}
|
|
1079
1079
|
|
|
1080
1080
|
if (typeof node === 'object' && !Array.isArray(node) && !(node instanceof RegExp)) {
|
|
@@ -1084,7 +1084,7 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
1084
1084
|
} else {
|
|
1085
1085
|
internal[key] = node
|
|
1086
1086
|
}
|
|
1087
|
-
}
|
|
1087
|
+
}
|
|
1088
1088
|
}
|
|
1089
1089
|
|
|
1090
1090
|
/**
|
|
@@ -1117,12 +1117,12 @@ Config.prototype._fromSpecial = function _fromSpecial() {
|
|
|
1117
1117
|
Config.prototype._featureFlagsFromEnv = function _featureFlagsFromEnv() {
|
|
1118
1118
|
const flags = Object.keys(featureFlag.prerelease).concat(featureFlag.released)
|
|
1119
1119
|
const config = this
|
|
1120
|
-
|
|
1120
|
+
for (const flag of flags) {
|
|
1121
1121
|
const envVal = process.env['NEW_RELIC_FEATURE_FLAG_' + flag.toUpperCase()]
|
|
1122
1122
|
if (envVal) {
|
|
1123
1123
|
config.feature_flag[flag] = isTruthular(envVal)
|
|
1124
1124
|
}
|
|
1125
|
-
}
|
|
1125
|
+
}
|
|
1126
1126
|
}
|
|
1127
1127
|
|
|
1128
1128
|
/**
|
|
@@ -1341,7 +1341,7 @@ Config.prototype._serverlessDT = function _serverlessDT() {
|
|
|
1341
1341
|
*/
|
|
1342
1342
|
Config.prototype._preventServerlessDT = function _preventServerlessDT() {
|
|
1343
1343
|
// Don't allow DT config settings to be set if serverless_mode is disabled
|
|
1344
|
-
|
|
1344
|
+
for (const key of SERVERLESS_DT_KEYS) {
|
|
1345
1345
|
if (this[key]) {
|
|
1346
1346
|
logger.warn(
|
|
1347
1347
|
key +
|
|
@@ -1350,7 +1350,7 @@ Config.prototype._preventServerlessDT = function _preventServerlessDT() {
|
|
|
1350
1350
|
)
|
|
1351
1351
|
this[key] = null
|
|
1352
1352
|
}
|
|
1353
|
-
}
|
|
1353
|
+
}
|
|
1354
1354
|
}
|
|
1355
1355
|
|
|
1356
1356
|
/**
|
|
@@ -1502,7 +1502,9 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
|
|
|
1502
1502
|
this.attributes.exclude.push('request.parameters.*')
|
|
1503
1503
|
|
|
1504
1504
|
function checkNode(base, target, settings) {
|
|
1505
|
-
Object.keys(settings)
|
|
1505
|
+
for (const key of Object.keys(settings)) {
|
|
1506
|
+
checkKey(base, target, settings, key)
|
|
1507
|
+
}
|
|
1506
1508
|
}
|
|
1507
1509
|
|
|
1508
1510
|
function checkKey(base, target, settings, key) {
|
|
@@ -1531,7 +1533,7 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
|
|
|
1531
1533
|
* @param {Array} keys keys from a LASP policy
|
|
1532
1534
|
* @returns {CollectorResponse} creates CollectorResponse with either preserve or shutdown
|
|
1533
1535
|
*/
|
|
1534
|
-
function
|
|
1536
|
+
function _laspResponse(keys) {
|
|
1535
1537
|
if (keys.length) {
|
|
1536
1538
|
logger.error('The agent received one or more unexpected security policies and will shut down.')
|
|
1537
1539
|
return CollectorResponse.fatal(null)
|
|
@@ -1617,18 +1619,18 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
|
1617
1619
|
const keys = Object.keys(policies)
|
|
1618
1620
|
|
|
1619
1621
|
if (!this.security_policies_token) {
|
|
1620
|
-
return
|
|
1622
|
+
return _laspResponse(keys)
|
|
1621
1623
|
}
|
|
1622
1624
|
|
|
1623
1625
|
const { finalPolicies, missingRequired } = this._buildLaspPolicy(agent, policies)
|
|
1624
1626
|
|
|
1625
1627
|
const missingLASP = []
|
|
1626
|
-
Object.keys(LASP_MAP)
|
|
1628
|
+
for (const name of Object.keys(LASP_MAP)) {
|
|
1627
1629
|
if (!policies[name]) {
|
|
1628
1630
|
// agent is expecting a policy that was not sent from server -- fail
|
|
1629
1631
|
missingLASP.push(name)
|
|
1630
1632
|
}
|
|
1631
|
-
}
|
|
1633
|
+
}
|
|
1632
1634
|
|
|
1633
1635
|
let fatalMessage = null
|
|
1634
1636
|
if (missingLASP.length) {
|
|
@@ -1655,14 +1657,14 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
|
1655
1657
|
}
|
|
1656
1658
|
|
|
1657
1659
|
Config.prototype.validateFlags = function validateFlags() {
|
|
1658
|
-
Object.keys(this.feature_flag)
|
|
1660
|
+
for (const key of Object.keys(this.feature_flag)) {
|
|
1659
1661
|
if (featureFlag.released.indexOf(key) > -1) {
|
|
1660
1662
|
logger.warn('Feature flag %s has been released', key)
|
|
1661
1663
|
}
|
|
1662
1664
|
if (featureFlag.unreleased.indexOf(key) > -1) {
|
|
1663
1665
|
logger.warn('Feature flag %s has been deprecated', key)
|
|
1664
1666
|
}
|
|
1665
|
-
}
|
|
1667
|
+
}
|
|
1666
1668
|
}
|
|
1667
1669
|
|
|
1668
1670
|
function redactValue(value) {
|
|
@@ -32,28 +32,28 @@ class MergeServerConfig {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
updateArray(value, local, localKey) {
|
|
35
|
-
|
|
35
|
+
for (const element of value) {
|
|
36
36
|
if (local[localKey].indexOf(element) === -1) {
|
|
37
37
|
local[localKey].push(element)
|
|
38
38
|
}
|
|
39
|
-
}
|
|
39
|
+
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
updateObject(value, local, localKey) {
|
|
43
43
|
// go through each key of the object and update it
|
|
44
|
-
Object.keys(value)
|
|
44
|
+
for (const element of Object.keys(value)) {
|
|
45
45
|
if (Array.isArray(local[localKey][element]) && Array.isArray(value[element])) {
|
|
46
46
|
// if both key-values are arrays, push the remote value onto the local array
|
|
47
|
-
value[element]
|
|
47
|
+
for (const elementValue of value[element]) {
|
|
48
48
|
if (local[localKey][element].indexOf(elementValue) === -1) {
|
|
49
49
|
local[localKey][element].push(elementValue)
|
|
50
50
|
}
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
} else {
|
|
53
53
|
// otherwise, replace the local value with the server value
|
|
54
54
|
local[localKey][element] = value[element]
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -32,6 +32,10 @@ module.exports = {
|
|
|
32
32
|
type: InstrumentationDescriptor.TYPE_TRANSACTION,
|
|
33
33
|
file: 'http.js'
|
|
34
34
|
},
|
|
35
|
+
http2: {
|
|
36
|
+
type: InstrumentationDescriptor.TYPE_TRANSACTION,
|
|
37
|
+
file: 'http2.js'
|
|
38
|
+
},
|
|
35
39
|
inspector: {
|
|
36
40
|
type: InstrumentationDescriptor.TYPE_GENERIC,
|
|
37
41
|
file: 'inspector.js'
|
|
@@ -72,18 +72,19 @@ function parsePath(pathString, method) {
|
|
|
72
72
|
operation = 'index.create'
|
|
73
73
|
return { collection, operation }
|
|
74
74
|
}
|
|
75
|
-
path.
|
|
75
|
+
for (let idx = 0; idx < path.length; idx++) {
|
|
76
|
+
const segment = path[idx]
|
|
76
77
|
const prev = idx - 1
|
|
77
|
-
let opname
|
|
78
78
|
if (segment === '_search') {
|
|
79
79
|
collection = path?.[prev] || defaultCollection
|
|
80
80
|
operation = 'search'
|
|
81
81
|
} else if (segment[0] === '_') {
|
|
82
|
-
opname = segment.substring(1)
|
|
82
|
+
const opname = segment.substring(1)
|
|
83
83
|
collection = path?.[prev] || defaultCollection
|
|
84
84
|
operation = `${opname}.${suffix}`
|
|
85
85
|
}
|
|
86
|
-
}
|
|
86
|
+
}
|
|
87
|
+
|
|
87
88
|
if (!operation && !collection) {
|
|
88
89
|
// likely creating an index--no underscore segments
|
|
89
90
|
collection = path?.[1] || defaultCollection
|
|
@@ -40,7 +40,7 @@ module.exports = function parseSql(sql) {
|
|
|
40
40
|
try {
|
|
41
41
|
logger.trace('parseSQL got an a non-string sql that looks like: %s', stringify(sql))
|
|
42
42
|
} catch (err) {
|
|
43
|
-
logger.debug(err, '
|
|
43
|
+
logger.debug(err, 'Unable to stringify SQL')
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
return {
|
package/lib/environment.js
CHANGED
|
@@ -240,7 +240,7 @@ function getGlobalPackages() {
|
|
|
240
240
|
*/
|
|
241
241
|
function flattenVersions(packages) {
|
|
242
242
|
const info = Object.create(null)
|
|
243
|
-
|
|
243
|
+
for (const pair of packages) {
|
|
244
244
|
const p = pair[0]
|
|
245
245
|
const v = pair[1]
|
|
246
246
|
|
|
@@ -251,7 +251,7 @@ function flattenVersions(packages) {
|
|
|
251
251
|
} else {
|
|
252
252
|
info[p] = [v]
|
|
253
253
|
}
|
|
254
|
-
}
|
|
254
|
+
}
|
|
255
255
|
|
|
256
256
|
return Object.keys(info)
|
|
257
257
|
.map((key) => [key, info[key].join(', ')])
|
|
@@ -277,7 +277,7 @@ function flattenVersions(packages) {
|
|
|
277
277
|
function remapConfigSettings() {
|
|
278
278
|
if (process.config && process.config.variables) {
|
|
279
279
|
const variables = process.config.variables
|
|
280
|
-
Object.keys(variables)
|
|
280
|
+
for (const key of Object.keys(variables)) {
|
|
281
281
|
if (remapping[key]) {
|
|
282
282
|
let value = variables[key]
|
|
283
283
|
|
|
@@ -290,7 +290,7 @@ function remapConfigSettings() {
|
|
|
290
290
|
|
|
291
291
|
addSetting(remapping[key], value)
|
|
292
292
|
}
|
|
293
|
-
}
|
|
293
|
+
}
|
|
294
294
|
|
|
295
295
|
addMissingProcessVars()
|
|
296
296
|
}
|
|
@@ -334,10 +334,10 @@ async function getOtherPackages() {
|
|
|
334
334
|
2
|
|
335
335
|
)
|
|
336
336
|
|
|
337
|
-
|
|
337
|
+
for (const pkg of otherPackages) {
|
|
338
338
|
other.packages.push.apply(other.packages, pkg.packages)
|
|
339
339
|
other.dependencies.push.apply(other.dependencies, pkg.dependencies)
|
|
340
|
-
}
|
|
340
|
+
}
|
|
341
341
|
|
|
342
342
|
_log('Done getting other packages')
|
|
343
343
|
return other
|
|
@@ -442,21 +442,21 @@ function refreshSyncOnly() {
|
|
|
442
442
|
settings = Object.create(null)
|
|
443
443
|
// add persisted settings
|
|
444
444
|
if (framework.length) {
|
|
445
|
-
|
|
445
|
+
for (const fw of framework) {
|
|
446
446
|
addSetting('Framework', fw)
|
|
447
|
-
}
|
|
447
|
+
}
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
if (dispatcher.length) {
|
|
451
|
-
|
|
451
|
+
for (const d of dispatcher) {
|
|
452
452
|
addSetting('Dispatcher', d)
|
|
453
|
-
}
|
|
453
|
+
}
|
|
454
454
|
}
|
|
455
455
|
|
|
456
456
|
if (dispatcherVersion.length) {
|
|
457
|
-
|
|
457
|
+
for (const d of dispatcher) {
|
|
458
458
|
addSetting(DISPATCHER_VERSION, d)
|
|
459
|
-
}
|
|
459
|
+
}
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
gatherEnv()
|
|
@@ -498,11 +498,11 @@ async function getJSON() {
|
|
|
498
498
|
}
|
|
499
499
|
|
|
500
500
|
const items = []
|
|
501
|
-
Object.
|
|
502
|
-
|
|
501
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
502
|
+
for (const setting of value) {
|
|
503
503
|
items.push([key, setting])
|
|
504
|
-
}
|
|
505
|
-
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
506
|
_log('JSON got')
|
|
507
507
|
return items
|
|
508
508
|
}
|
package/lib/errors/index.js
CHANGED
|
@@ -58,7 +58,7 @@ class Exception {
|
|
|
58
58
|
* because everything's an object in JS. I'm not entirely sure why we do this, but
|
|
59
59
|
* weird enough to make note of
|
|
60
60
|
*
|
|
61
|
-
* @param {Transaction} transaction The agent transaction, coming from the
|
|
61
|
+
* @param {Transaction} transaction The agent transaction, coming from the instrumentation
|
|
62
62
|
* @param {Exception} exception An custom Exception object with the error and other information
|
|
63
63
|
* @param {object} config The configuration to use when creating the object
|
|
64
64
|
* @returns {Array} an Array of Error information, [0] -> placeholder,
|