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.
Files changed (37) hide show
  1. package/NEWS.md +42 -18
  2. package/THIRD_PARTY_NOTICES.md +203 -2
  3. package/api.js +155 -103
  4. package/lib/agent.js +29 -82
  5. package/lib/collector/api.js +234 -201
  6. package/lib/config/attribute-filter.js +35 -25
  7. package/lib/config/default.js +45 -19
  8. package/lib/config/index.js +260 -199
  9. package/lib/environment.js +16 -12
  10. package/lib/errors/error-collector.js +124 -55
  11. package/lib/errors/index.js +59 -49
  12. package/lib/instrumentation/@hapi/hapi.js +56 -50
  13. package/lib/instrumentation/@node-redis/client.js +50 -41
  14. package/lib/instrumentation/amqplib.js +116 -151
  15. package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -11
  16. package/lib/instrumentation/core/globals.js +1 -1
  17. package/lib/instrumentation/core/http-outbound.js +193 -78
  18. package/lib/instrumentation/core/timers.js +106 -59
  19. package/lib/instrumentation/grpc-js/grpc.js +20 -23
  20. package/lib/instrumentation/mongodb/common.js +87 -85
  21. package/lib/instrumentation/redis.js +112 -90
  22. package/lib/instrumentation/undici.js +204 -192
  23. package/lib/instrumentation/{when.js → when/constants.js} +13 -10
  24. package/lib/instrumentation/when/contextualizer.js +168 -0
  25. package/lib/instrumentation/when/index.js +354 -0
  26. package/lib/instrumentation/when/nr-hooks.js +15 -0
  27. package/lib/instrumentations.js +1 -1
  28. package/lib/shim/shim.js +2 -0
  29. package/lib/shim/webframework-shim.js +19 -0
  30. package/lib/symbols.js +1 -0
  31. package/lib/system-info.js +240 -163
  32. package/lib/util/async-each-limit.js +30 -0
  33. package/lib/util/attributes.js +159 -0
  34. package/lib/util/code-level-metrics.js +58 -0
  35. package/lib/util/deep-equal.js +11 -144
  36. package/package.json +5 -4
  37. 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
+ }
@@ -5,152 +5,19 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- /* eslint sonarjs/cognitive-complexity: ["error", 35] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
8
+ const util = require('util')
9
9
 
10
- function isArguments(object) {
11
- return Object.prototype.toString.call(object) === '[object Arguments]'
12
- }
13
-
14
- function slice(args) {
15
- // Array.prototype.slice on arguments array-like is expensive
16
- const l = args.length
17
- const a = []
18
- let i
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
- let cal = ca.length
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.0",
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.5.5",
182
- "@grpc/proto-loader": "^0.6.13",
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",