newrelic 9.7.0 → 9.7.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/NEWS.md +42 -18
- package/THIRD_PARTY_NOTICES.md +203 -2
- package/api.js +155 -103
- package/lib/agent.js +29 -82
- package/lib/collector/api.js +234 -201
- package/lib/config/attribute-filter.js +35 -25
- package/lib/config/default.js +45 -19
- package/lib/config/index.js +260 -199
- package/lib/environment.js +16 -12
- package/lib/errors/error-collector.js +124 -55
- package/lib/errors/index.js +59 -49
- package/lib/instrumentation/@hapi/hapi.js +56 -50
- package/lib/instrumentation/@node-redis/client.js +50 -41
- package/lib/instrumentation/amqplib.js +116 -151
- package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -11
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +193 -78
- package/lib/instrumentation/core/timers.js +106 -59
- package/lib/instrumentation/grpc-js/grpc.js +20 -23
- package/lib/instrumentation/mongodb/common.js +87 -85
- package/lib/instrumentation/redis.js +112 -90
- package/lib/instrumentation/undici.js +204 -192
- package/lib/instrumentation/{when.js → when/constants.js} +13 -10
- package/lib/instrumentation/when/contextualizer.js +168 -0
- package/lib/instrumentation/when/index.js +354 -0
- package/lib/instrumentation/when/nr-hooks.js +15 -0
- package/lib/instrumentations.js +1 -1
- package/lib/shim/shim.js +2 -0
- package/lib/shim/webframework-shim.js +19 -0
- package/lib/symbols.js +1 -0
- package/lib/system-info.js +240 -163
- package/lib/util/async-each-limit.js +30 -0
- package/lib/util/attributes.js +159 -0
- package/lib/util/code-level-metrics.js +58 -0
- package/lib/util/deep-equal.js +11 -144
- package/package.json +5 -4
- package/lib/instrumentation/promise.js +0 -572
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const logger = require('../logger').child({ component: 'code-level-metrics' })
|
|
8
|
+
const { isValidLength } = require('./byte-limit')
|
|
9
|
+
const symbols = require('../symbols')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Uses function name if truthy
|
|
13
|
+
* otherwise it defaults to (anonymous)
|
|
14
|
+
*
|
|
15
|
+
* @param {string} name name of function
|
|
16
|
+
* @returns {string} function name or (anonymous)
|
|
17
|
+
*/
|
|
18
|
+
function setFunctionName(name) {
|
|
19
|
+
return name || '(anonymous)'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Helper used to assign Code Level Metrics(CLM)
|
|
24
|
+
* to an active segment.
|
|
25
|
+
*
|
|
26
|
+
* spec states if function or filepath are > 255, do not assign
|
|
27
|
+
* CLM attrs
|
|
28
|
+
*
|
|
29
|
+
* @param {Function} fn function reference
|
|
30
|
+
* @param {TraceSegment} segment active segment to attach code.* attrs
|
|
31
|
+
*/
|
|
32
|
+
module.exports = function addCLMAttributes(fn, segment) {
|
|
33
|
+
if (!fn[symbols.clm]) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const { funcInfo } = require('@contrast/fn-inspect')
|
|
39
|
+
const { lineNumber, method, file: filePath, column } = funcInfo(fn)
|
|
40
|
+
const fnName = setFunctionName(method)
|
|
41
|
+
|
|
42
|
+
if (isValidLength(fnName, 255) && isValidLength(filePath, 255)) {
|
|
43
|
+
segment.addAttribute('code.filepath', filePath)
|
|
44
|
+
segment.addAttribute('code.function', fnName)
|
|
45
|
+
// both line numbers and columns start at 0 in v8, add 1 to reflect js code
|
|
46
|
+
// See: https://v8.github.io/api/head/classv8_1_1Function.html#a87bc63f97a9a39f83051570519fc63c2
|
|
47
|
+
segment.addAttribute('code.lineno', lineNumber + 1)
|
|
48
|
+
segment.addAttribute('code.column', column + 1)
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
logger.infoOnce({ err }, 'Not using v8 function inspector, falling back to function name')
|
|
52
|
+
const fnName = setFunctionName(fn.name)
|
|
53
|
+
|
|
54
|
+
if (isValidLength(fnName, 255)) {
|
|
55
|
+
segment.addAttribute('code.function', fnName)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
package/lib/util/deep-equal.js
CHANGED
|
@@ -5,152 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const util = require('util')
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
for (i = 0; i < l; i++) {
|
|
20
|
-
a[i] = args[i]
|
|
21
|
-
}
|
|
22
|
-
return a
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* This is a node-specific version of deepEquals, modeled on bits and pieces
|
|
27
|
-
* of loads of other implementations of this algorithm, most notably the
|
|
28
|
-
* one in the Node.js source and Underscore's. It doesn't throw and handles
|
|
29
|
-
* cycles.
|
|
30
|
-
*
|
|
31
|
-
* Everybody who writes one of these functions puts the documentation
|
|
32
|
-
* inline, which makes it incredibly hard to follow. Here's what this version
|
|
33
|
-
* of the algorithm does, in order:
|
|
34
|
-
*
|
|
35
|
-
* 1. === only tests objects and and functions by reference. Null is an object.
|
|
36
|
-
* Any pair of identical entities failing this test are therefore objects
|
|
37
|
-
* (including null), which need a recursive compare by attribute.
|
|
38
|
-
* 2. Since the only matching entities to get to this test must be objects, if
|
|
39
|
-
* a or b is not an object, they're clearly not the same. All unfiltered a
|
|
40
|
-
* and b getting are objects (including null).
|
|
41
|
-
* 3. null is an object, but null === null. All unfiltered a and b are non-null
|
|
42
|
-
* objects.
|
|
43
|
-
* 4. Buffers need to be special-cased because they live partially on the wrong
|
|
44
|
-
* side of the C++ / JavaScript barrier. Still, calling this on structures
|
|
45
|
-
* that can contain Buffers is a bad idea, because they can contain
|
|
46
|
-
* multiple megabytes of data and comparing them byte-by-byte is very
|
|
47
|
-
* expensive. buffertools is a better solution here, but this version of
|
|
48
|
-
* this code is dependency free.
|
|
49
|
-
* 5. It's much faster to compare dates by numeric value than by lexical value.
|
|
50
|
-
* 6. Same goes for Regexps.
|
|
51
|
-
* 7. The parts of an arguments list most people care about are the arguments
|
|
52
|
-
* themselves, not the callee, which you shouldn't be looking at anyway.
|
|
53
|
-
* 8. Objects are more complex:
|
|
54
|
-
* a. ensure that a and b are on the same constructor chain
|
|
55
|
-
* b. ensure that a and b have the same number of own properties (which is
|
|
56
|
-
* what Object.keys returns).
|
|
57
|
-
* c. ensure that cyclical references don't blow up the stack.
|
|
58
|
-
* d. ensure that all the key names match (faster)
|
|
59
|
-
* e. ensure that all of the associated values match, recursively (slower)
|
|
60
|
-
*
|
|
61
|
-
* (SOMEWHAT UNTESTED) ASSUMPTIONS:
|
|
62
|
-
*
|
|
63
|
-
* o Functions are only considered identical if they unify to the same
|
|
64
|
-
* reference. To anything else is to invite the wrath of the halting problem.
|
|
65
|
-
* o V8 is smart enough to optimize treating an Array like any other kind of
|
|
66
|
-
* object.
|
|
67
|
-
* o Users of this function are cool with mutually recursive data structures
|
|
68
|
-
* that are otherwise identical being treated as the same.
|
|
69
|
-
*
|
|
70
|
-
* @param a
|
|
71
|
-
* @param b
|
|
72
|
-
* @param ca
|
|
73
|
-
* @param cb
|
|
74
|
-
*/
|
|
75
|
-
function deeper(a, b, ca, cb) {
|
|
76
|
-
if (a === b) {
|
|
77
|
-
return true
|
|
78
|
-
} else if (typeof a !== 'object' || typeof b !== 'object') {
|
|
79
|
-
return false
|
|
80
|
-
} else if (a === null || b === null) {
|
|
81
|
-
return false
|
|
82
|
-
} else if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) {
|
|
83
|
-
if (a.length !== b.length) {
|
|
84
|
-
return false
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// potentially incredibly expensive
|
|
88
|
-
for (let i = 0; i < a.length; i++) {
|
|
89
|
-
if (a[i] !== b[i]) {
|
|
90
|
-
return false
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return true
|
|
95
|
-
} else if (a instanceof Date && b instanceof Date) {
|
|
96
|
-
return a.getTime() === b.getTime()
|
|
97
|
-
} else if (a instanceof RegExp && b instanceof RegExp) {
|
|
98
|
-
return (
|
|
99
|
-
a.source === b.source &&
|
|
100
|
-
a.global === b.global &&
|
|
101
|
-
a.multiline === b.multiline &&
|
|
102
|
-
a.lastIndex === b.lastIndex &&
|
|
103
|
-
a.ignoreCase === b.ignoreCase
|
|
104
|
-
)
|
|
105
|
-
} else if (isArguments(a) || isArguments(b)) {
|
|
106
|
-
if (!(isArguments(a) && isArguments(b))) {
|
|
107
|
-
return false
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return deeper(slice(a), slice(b), ca, cb)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (a.constructor !== b.constructor) {
|
|
114
|
-
return false
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const ka = Object.keys(a)
|
|
118
|
-
const kb = Object.keys(b)
|
|
119
|
-
if (ka.length !== kb.length) {
|
|
10
|
+
module.exports = function exports(a, b) {
|
|
11
|
+
/*
|
|
12
|
+
* NaN is a special case, util.isDeepStrictEqual will return true for comparing two NaNs,
|
|
13
|
+
* but comparing a NaN to itself like this returns false (yay for weird JS stuff)
|
|
14
|
+
*
|
|
15
|
+
* Added this special check because the original implementation of this
|
|
16
|
+
* did not consider two NaNs as equal, so preserving existing functionality
|
|
17
|
+
*/
|
|
18
|
+
if (a !== a && b !== b) {
|
|
120
19
|
return false
|
|
121
20
|
}
|
|
122
21
|
|
|
123
|
-
|
|
124
|
-
while (cal--) {
|
|
125
|
-
if (ca[cal] === a) {
|
|
126
|
-
return cb[cal] === b
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
ca.push(a)
|
|
130
|
-
cb.push(b)
|
|
131
|
-
|
|
132
|
-
ka.sort()
|
|
133
|
-
kb.sort()
|
|
134
|
-
for (let j = ka.length - 1; j >= 0; j--) {
|
|
135
|
-
if (ka[j] !== kb[j]) {
|
|
136
|
-
return false
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
let key
|
|
141
|
-
for (let k = ka.length - 1; k >= 0; k--) {
|
|
142
|
-
key = ka[k]
|
|
143
|
-
if (!deeper(a[key], b[key], ca, cb)) {
|
|
144
|
-
return false
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
ca.pop()
|
|
149
|
-
cb.pop()
|
|
150
|
-
|
|
151
|
-
return true
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
module.exports = function exports(a, b) {
|
|
155
|
-
return deeper(a, b, [], [])
|
|
22
|
+
return util.isDeepStrictEqual(a, b)
|
|
156
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newrelic",
|
|
3
|
-
"version": "9.7.
|
|
3
|
+
"version": "9.7.2",
|
|
4
4
|
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"contributors": [
|
|
@@ -178,8 +178,8 @@
|
|
|
178
178
|
"newrelic-naming-rules": "./bin/test-naming-rules.js"
|
|
179
179
|
},
|
|
180
180
|
"dependencies": {
|
|
181
|
-
"@grpc/grpc-js": "^1.
|
|
182
|
-
"@grpc/proto-loader": "^0.
|
|
181
|
+
"@grpc/grpc-js": "^1.7.3",
|
|
182
|
+
"@grpc/proto-loader": "^0.7.3",
|
|
183
183
|
"@newrelic/aws-sdk": "^5.0.0",
|
|
184
184
|
"@newrelic/koa": "^7.0.0",
|
|
185
185
|
"@newrelic/superagent": "^6.0.0",
|
|
@@ -192,7 +192,8 @@
|
|
|
192
192
|
"winston-transport": "^4.5.0"
|
|
193
193
|
},
|
|
194
194
|
"optionalDependencies": {
|
|
195
|
-
"@newrelic/native-metrics": "^9.0.0"
|
|
195
|
+
"@newrelic/native-metrics": "^9.0.0",
|
|
196
|
+
"@contrast/fn-inspect": "^3.3.0"
|
|
196
197
|
},
|
|
197
198
|
"devDependencies": {
|
|
198
199
|
"@newrelic/eslint-config": "^0.2.0",
|