newrelic 9.5.0 → 9.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.
Files changed (104) hide show
  1. package/NEWS.md +14 -0
  2. package/api.js +2 -0
  3. package/bin/test-naming-rules.js +1 -1
  4. package/esm-loader.mjs +1 -3
  5. package/index.js +6 -5
  6. package/lib/adaptive-sampler.js +1 -2
  7. package/lib/agent.js +2 -0
  8. package/lib/aggregators/event-aggregator.js +2 -2
  9. package/lib/attributes.js +2 -4
  10. package/lib/collector/api.js +20 -12
  11. package/lib/collector/facts.js +1 -3
  12. package/lib/collector/parse-response.js +3 -1
  13. package/lib/collector/remote-method.js +10 -10
  14. package/lib/config/attribute-filter.js +14 -16
  15. package/lib/config/default.js +544 -286
  16. package/lib/config/formatters.js +108 -0
  17. package/lib/config/harvest-config-validator.js +3 -5
  18. package/lib/config/index.js +74 -93
  19. package/lib/environment.js +6 -5
  20. package/lib/errors/error-collector.js +6 -3
  21. package/lib/errors/helper.js +10 -18
  22. package/lib/errors/index.js +12 -6
  23. package/lib/grpc/connection.js +12 -5
  24. package/lib/header-attributes.js +4 -2
  25. package/lib/header-processing.js +2 -2
  26. package/lib/instrumentation/@hapi/hapi.js +231 -1
  27. package/lib/instrumentation/{vision.js → @hapi/vision.js} +0 -0
  28. package/lib/instrumentation/@node-redis/client.js +2 -0
  29. package/lib/instrumentation/amqplib.js +2 -0
  30. package/lib/instrumentation/core/async_hooks.js +3 -4
  31. package/lib/instrumentation/core/globals.js +12 -10
  32. package/lib/instrumentation/core/http-outbound.js +17 -17
  33. package/lib/instrumentation/core/http.js +16 -27
  34. package/lib/instrumentation/core/timers.js +5 -1
  35. package/lib/instrumentation/fastify.js +1 -3
  36. package/lib/instrumentation/grpc-js/grpc.js +14 -3
  37. package/lib/instrumentation/memcached.js +5 -0
  38. package/lib/instrumentation/mongodb/common.js +3 -0
  39. package/lib/instrumentation/mongodb/v2-mongo.js +6 -3
  40. package/lib/instrumentation/mongodb.js +1 -1
  41. package/lib/instrumentation/mysql/mysql.js +6 -5
  42. package/lib/instrumentation/nr-winston-transport.js +3 -4
  43. package/lib/instrumentation/promise.js +22 -18
  44. package/lib/instrumentation/redis.js +2 -0
  45. package/lib/instrumentation/undici.js +12 -15
  46. package/lib/instrumentations.js +1 -1
  47. package/lib/metrics/mapper.js +2 -3
  48. package/lib/metrics/metric-aggregator.js +1 -3
  49. package/lib/metrics/names.js +19 -15
  50. package/lib/metrics/normalizer/rule.js +6 -7
  51. package/lib/metrics/normalizer/tx_segment.js +3 -2
  52. package/lib/metrics/normalizer.js +5 -3
  53. package/lib/parse-proc-cpuinfo.js +11 -6
  54. package/lib/serverless/api-gateway.js +3 -4
  55. package/lib/serverless/aws-lambda.js +3 -3
  56. package/lib/shim/conglomerate-shim.js +2 -3
  57. package/lib/shim/constants.js +1 -16
  58. package/lib/shim/datastore-shim.js +24 -105
  59. package/lib/shim/index.js +7 -0
  60. package/lib/shim/message-shim.js +2 -0
  61. package/lib/shim/promise-shim.js +66 -59
  62. package/lib/shim/shim.js +44 -89
  63. package/lib/shim/transaction-shim.js +1 -1
  64. package/lib/shim/webframework-shim.js +4 -8
  65. package/lib/shimmer.js +29 -23
  66. package/lib/spans/map-to-streaming-type.js +0 -2
  67. package/lib/spans/span-context.js +2 -0
  68. package/lib/spans/span-event-aggregator.js +2 -2
  69. package/lib/spans/span-event.js +2 -2
  70. package/lib/spans/span-streamer.js +4 -0
  71. package/lib/spans/streaming-span-event-aggregator.js +2 -4
  72. package/lib/spans/streaming-span-event.js +3 -2
  73. package/lib/symbols.js +26 -0
  74. package/lib/system-info.js +4 -7
  75. package/lib/timer.js +8 -6
  76. package/lib/transaction/dt-payload.js +4 -3
  77. package/lib/transaction/handle.js +12 -2
  78. package/lib/transaction/index.js +19 -18
  79. package/lib/transaction/name-state.js +17 -2
  80. package/lib/transaction/trace/aggregator.js +4 -12
  81. package/lib/transaction/trace/index.js +7 -5
  82. package/lib/transaction/trace/segment.js +6 -11
  83. package/lib/transaction/tracecontext.js +10 -6
  84. package/lib/transaction/tracer/index.js +35 -43
  85. package/lib/transaction/transaction-event-aggregator.js +1 -3
  86. package/lib/util/arity.js +4 -9
  87. package/lib/util/attribute-types.js +1 -2
  88. package/lib/util/byte-limit.js +1 -3
  89. package/lib/util/cat.js +16 -13
  90. package/lib/util/codec.js +0 -2
  91. package/lib/util/copy.js +1 -2
  92. package/lib/util/deep-equal.js +7 -0
  93. package/lib/util/flatten.js +4 -6
  94. package/lib/util/hashes.js +1 -3
  95. package/lib/util/process-version.js +2 -3
  96. package/lib/util/properties.js +2 -51
  97. package/lib/util/stream-sink.js +2 -0
  98. package/lib/util/urltils.js +4 -10
  99. package/newrelic.js +1 -1
  100. package/package.json +2 -1
  101. package/lib/config/env.js +0 -294
  102. package/lib/instrumentation/hapi/hapi.js +0 -207
  103. package/lib/instrumentation/hapi/shared.js +0 -28
  104. package/lib/instrumentation/hapi.js +0 -254
@@ -5,4 +5,234 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- module.exports = require('../hapi')
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 68] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
10
+ const record = require('../../metrics/recorders/generic')
11
+ // This object defines all the events that we want to wrap extensions
12
+ // for, as they are the only ones associated with requests.
13
+ const ROUTE_EVENTS = {
14
+ onRequest: true,
15
+ onPreAuth: true,
16
+ onCredentials: true,
17
+ onPostAuth: true,
18
+ onPreHandler: true,
19
+ onPostHandler: true,
20
+ onPreResponse: true,
21
+
22
+ // Server events
23
+ onPreStart: false,
24
+ onPostStart: false,
25
+ onPreStop: false,
26
+ onPostStop: false
27
+ }
28
+
29
+ module.exports = function initialize(agent, hapi, moduleName, shim) {
30
+ if (!agent || !hapi || !shim) {
31
+ shim &&
32
+ shim.logger.debug(
33
+ 'Hapi instrumentation function called with incorrect arguments, not instrumenting.'
34
+ )
35
+ return false
36
+ }
37
+
38
+ shim.setFramework(shim.HAPI)
39
+
40
+ shim.setErrorPredicate(function hapiErrorPredicate(err) {
41
+ return err instanceof Error
42
+ })
43
+
44
+ // At this point, framework and error predicate have both already been set via ./hapi,
45
+ // so we only need to set the response predicate and wrap the server object
46
+ shim.setResponsePredicate(function hapiResponsePredicate(args, result) {
47
+ return !(result instanceof Error) && result !== args[1].continue
48
+ })
49
+
50
+ // 'Server' and 'server' both point to the same export,
51
+ // but we can't make any assumption about which will be used.
52
+ // Since we wrap the prototype, the second wrap should exit early.
53
+ shim.wrapReturn(hapi, 'server', serverFactoryWrapper)
54
+ shim.wrapReturn(hapi, 'Server', serverFactoryWrapper)
55
+ }
56
+
57
+ function serverFactoryWrapper(shim, fn, fnName, server) {
58
+ serverPostConstructor.call(server, shim)
59
+ }
60
+
61
+ function serverPostConstructor(shim) {
62
+ const proto = Object.getPrototypeOf(this)
63
+
64
+ if (shim.isWrapped(proto.decorate)) {
65
+ shim.logger.trace('Already wrapped Server proto, not wrapping again')
66
+ return
67
+ }
68
+
69
+ shim.wrap(proto, 'decorate', function wrapDecorate(shim, original) {
70
+ return function wrappedDecorate(type) {
71
+ // server.decorate also accepts 'request', 'toolkit', 'server' types,
72
+ // but we're only concerned with 'handler'
73
+ if (type !== 'handler') {
74
+ return original.apply(this, arguments)
75
+ }
76
+
77
+ // Convert arguments to usable array
78
+ const args = shim.argsToArray.apply(shim, arguments)
79
+
80
+ // Wrap the third server.decorate arg, the user-defined handler
81
+ shim.wrap(args, shim.THIRD, function wrapHandler(shim, fn) {
82
+ if (typeof fn !== 'function') {
83
+ return
84
+ }
85
+
86
+ if (fn.defaults) {
87
+ wrappedHandler.defaults = fn.defaults
88
+ }
89
+
90
+ return wrappedHandler
91
+
92
+ function wrappedHandler(route) {
93
+ const ret = fn.apply(this, arguments)
94
+
95
+ return typeof ret === 'function' ? wrapRouteHandler(shim, ret, route && route.path) : ret
96
+ }
97
+ })
98
+
99
+ return original.apply(this, args)
100
+ }
101
+ })
102
+
103
+ shim.wrap(proto, 'route', function wrapRoute(shim, original) {
104
+ return function wrappedRoute() {
105
+ const args = shim.argsToArray.apply(shim, arguments)
106
+
107
+ if (!shim.isObject(args[0])) {
108
+ return original.apply(this, args)
109
+ }
110
+
111
+ // If route is created via a plugin, pull prefix if it exists
112
+ const prefix =
113
+ (this.realm &&
114
+ this.realm.modifiers &&
115
+ this.realm.modifiers.route &&
116
+ this.realm.modifiers.route.prefix) ||
117
+ ''
118
+
119
+ _wrapRoute(shim, args[0])
120
+
121
+ return original.apply(this, args)
122
+
123
+ function _wrapRoute(shim, route) {
124
+ const routePath = prefix + route.path
125
+ if (shim.isArray(route)) {
126
+ for (let i = 0; i < route.length; ++i) {
127
+ _wrapRoute(shim, route[i])
128
+ }
129
+ return
130
+ } else if (route.options) {
131
+ // v17 now prefers `options` property...
132
+ if (route.options.pre) {
133
+ // config objects can also contain multiple OTHER handlers in a `pre` array
134
+ route.options.pre = wrapPreHandlers(shim, route.options.pre, routePath)
135
+ }
136
+ if (route.options.handler) {
137
+ _wrapRouteHandler(shim, route.options, routePath)
138
+ return
139
+ }
140
+ } else if (route.config) {
141
+ // ... but `config` still works
142
+ if (route.config.pre) {
143
+ route.config.pre = wrapPreHandlers(shim, route.config.pre, routePath)
144
+ }
145
+ if (route.config.handler) {
146
+ _wrapRouteHandler(shim, route.config, routePath)
147
+ return
148
+ }
149
+ }
150
+ _wrapRouteHandler(shim, route, routePath)
151
+ }
152
+
153
+ function _wrapRouteHandler(shim, container, path) {
154
+ if (typeof container.handler !== 'function') {
155
+ return
156
+ }
157
+ shim.wrap(container, 'handler', function wrapHandler(shim, handler) {
158
+ return wrapRouteHandler(shim, handler, path)
159
+ })
160
+ }
161
+ }
162
+ })
163
+
164
+ shim.wrap(proto, 'ext', function wrapExt(shim, original) {
165
+ return function wrappedExt(event, method) {
166
+ const args = shim.argsToArray.apply(shim, arguments)
167
+
168
+ if (shim.isArray(event)) {
169
+ for (let i = 0; i < event.length; i++) {
170
+ event[i].method = wrapMiddleware(shim, event[i].method, event[i].type)
171
+ }
172
+ } else if (shim.isObject(event)) {
173
+ event.method = wrapMiddleware(shim, event.method, event.type)
174
+ } else if (shim.isString(event)) {
175
+ args[1] = wrapMiddleware(shim, method, event)
176
+ } else {
177
+ shim.logger.debug('Unsupported event type %j', event)
178
+ return
179
+ }
180
+
181
+ return original.apply(this, args)
182
+ }
183
+ })
184
+ }
185
+
186
+ function wrapPreHandlers(shim, container, path) {
187
+ if (shim.isArray(container)) {
188
+ for (let i = 0; i < container.length; ++i) {
189
+ container[i] = wrapPreHandlers(shim, container[i], path)
190
+ }
191
+ return container
192
+ } else if (shim.isFunction(container)) {
193
+ return wrapPreHandler(shim, container, path)
194
+ } else if (container.method && shim.isFunction(container.method)) {
195
+ return shim.wrap(container, 'method', function wrapHandler(shim, handler) {
196
+ return wrapPreHandler(shim, handler, path)
197
+ })
198
+ }
199
+ }
200
+
201
+ function wrapPreHandler(shim, container, path) {
202
+ return shim.record(container, (shim) => {
203
+ return { name: [shim.HAPI, ' pre handler: ', '(', path, ')'].join(''), recorder: record }
204
+ })
205
+ }
206
+
207
+ function wrapRouteHandler(shim, handler, path) {
208
+ return shim.recordMiddleware(handler, {
209
+ route: path,
210
+ req: function getReq(shim, fn, fnName, args) {
211
+ const request = args[0]
212
+ if (request && request.raw) {
213
+ return request.raw.req
214
+ }
215
+ },
216
+ promise: true,
217
+ params: function getParams(shim, fn, fnName, args) {
218
+ const req = args[0]
219
+ return req && req.params
220
+ }
221
+ })
222
+ }
223
+
224
+ function wrapMiddleware(shim, middleware, event) {
225
+ if (!ROUTE_EVENTS[event]) {
226
+ return middleware
227
+ }
228
+
229
+ return shim.recordMiddleware(middleware, {
230
+ route: event,
231
+ type: event === 'onPreResponse' ? shim.ERRORWARE : shim.MIDDLEWARE,
232
+ promise: true,
233
+ req: function getReq(shim, fn, fnName, args) {
234
+ const req = args[0]
235
+ return req && req.raw && req.raw.req
236
+ }
237
+ })
238
+ }
@@ -3,6 +3,8 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
+ /* eslint sonarjs/cognitive-complexity: ["error", 20] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
7
+
6
8
  'use strict'
7
9
  const CLIENT_COMMANDS = ['select', 'quit', 'SELECT', 'QUIT']
8
10
 
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 16] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252*/
9
+
8
10
  const url = require('url')
9
11
 
10
12
  // TODO: Make this an external module.
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 18] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
8
10
  const logger = require('../../logger').child({ component: 'async_hooks' })
9
11
  const asyncHooks = require('async_hooks')
10
12
 
@@ -38,7 +40,7 @@ function initialize(agent, shim) {
38
40
 
39
41
  function getPromiseResolveStyleHooks(segmentMap, agent, shim) {
40
42
  const hooks = {
41
- init: function initHook(id, type, triggerId, asyncResource) {
43
+ init: function initHook(id, type, triggerId) {
42
44
  if (type !== 'PROMISE') {
43
45
  return
44
46
  }
@@ -55,9 +57,6 @@ function getPromiseResolveStyleHooks(segmentMap, agent, shim) {
55
57
  }
56
58
 
57
59
  const activeSegment = shim.getActiveSegment() || parentSegment
58
- if (asyncResource && asyncResource.promise) {
59
- asyncResource.promise.__NR_id = id
60
- }
61
60
 
62
61
  segmentMap.set(id, activeSegment)
63
62
  },
@@ -6,6 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  const asyncHooks = require('./async_hooks')
9
+ const symbols = require('../../symbols')
9
10
 
10
11
  module.exports = initialize
11
12
 
@@ -37,16 +38,17 @@ function initialize(agent, nodule, name, shim) {
37
38
  return function wrappedEmit(ev, error, promise) {
38
39
  // Check for unhandledRejections here so we don't change the behavior of
39
40
  // the event.
40
- if (ev === 'unhandledRejection' && error && !process.domain) {
41
- if (process.listenerCount('unhandledRejection') === 0) {
42
- // If there are no unhandledRejection handlers report the error.
43
- const segment = promise.__NR_id
44
- ? asyncHooks.segmentMap.get(promise.__NR_id)
45
- : promise.__NR_context && promise.__NR_context.getSegment()
46
- const tx = segment && segment.transaction
47
- shim.logger.trace('Captured unhandled rejection for transaction %s', tx && tx.id)
48
- agent.errors.add(tx, error)
49
- }
41
+ if (
42
+ ev === 'unhandledRejection' &&
43
+ error &&
44
+ !process.domain &&
45
+ process.listenerCount('unhandledRejection') === 0
46
+ ) {
47
+ // If there are no unhandledRejection handlers report the error.
48
+ const segment = promise[symbols.context] && promise[symbols.context].getSegment()
49
+ const tx = segment && segment.transaction
50
+ shim.logger.trace('Captured unhandled rejection for transaction %s', tx && tx.id)
51
+ agent.errors.add(tx, error)
50
52
  }
51
53
 
52
54
  return original.apply(this, arguments)
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 40] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
8
10
  const recordExternal = require('../../metrics/recorders/http_external')
9
11
  const cat = require('../../util/cat')
10
12
  const urltils = require('../../util/urltils')
@@ -12,9 +14,9 @@ const logger = require('../../logger').child({ component: 'outbound' })
12
14
  const shimmer = require('../../shimmer')
13
15
  const url = require('url')
14
16
  const copy = require('../../util/copy')
17
+ const symbols = require('../../symbols')
15
18
 
16
19
  const NAMES = require('../../metrics/names')
17
- const SHIM_SYMBOLS = require('../../shim/constants').SYMBOLS
18
20
 
19
21
  const DEFAULT_HOST = 'localhost'
20
22
  const DEFAULT_HTTP_PORT = 80
@@ -25,10 +27,10 @@ const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
25
27
  /**
26
28
  * Instruments an outbound HTTP request.
27
29
  *
28
- * @param {Agent} agent
29
- * @param {object} opts
30
- * @param {Function} makeRequest
31
- * @returns {http.ClientRequest} The instrumented outbound request.
30
+ * @param {object} agent instantiation of lib/agent.js
31
+ * @param {object} opts HTTP request options
32
+ * @param {Function} makeRequest function for issuing actual HTTP request
33
+ * @returns {object} The instrumented outbound HTTP request.
32
34
  */
33
35
  module.exports = function instrumentOutbound(agent, opts, makeRequest) {
34
36
  if (typeof opts === 'string') {
@@ -85,7 +87,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
85
87
 
86
88
  // TODO: abstract header logic shared with TransactionShim#insertCATRequestHeaders
87
89
  if (agent.config.distributed_tracing.enabled) {
88
- if (opts.headers && opts.headers[SHIM_SYMBOLS.DISABLE_DT]) {
90
+ if (opts.headers && opts.headers[symbols.disableDT]) {
89
91
  logger.trace('Distributed tracing disabled by instrumentation.')
90
92
  } else {
91
93
  transaction.insertDistributedTraceHeaders(outboundHeaders)
@@ -113,9 +115,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
113
115
  const parsed = urltils.scrubAndParseParameters(request.path)
114
116
  const proto = parsed.protocol || opts.protocol || 'http:'
115
117
  segment.name += parsed.path
116
- Object.defineProperty(request, '__NR_segment', {
117
- value: segment
118
- })
118
+ request[symbols.segment] = segment
119
119
 
120
120
  if (parsed.parameters) {
121
121
  // Scrub and parse returns on object with a null prototype.
@@ -153,10 +153,10 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
153
153
  * Notices the given error if there is no listener for the `error` event on the
154
154
  * request object.
155
155
  *
156
- * @param {TraceSegment} segment
157
- * @param {http.ClientRequest} req
158
- * @param {Error} error
159
- * @returns {bool} True if the error will be collected by New Relic.
156
+ * @param {object} segment TraceSegment instance
157
+ * @param {object} req http.ClientRequest
158
+ * @param {Error} error If provided, unhandled error that occurred during request
159
+ * @returns {boolean} True if the error will be collected by New Relic.
160
160
  */
161
161
  function handleError(segment, req, error) {
162
162
  if (req.listenerCount('error') > 0) {
@@ -173,10 +173,10 @@ function handleError(segment, req, error) {
173
173
  /**
174
174
  * Ties the response object to the request segment.
175
175
  *
176
- * @param {TraceSegment} segment
177
- * @param {string} hostname
178
- * @param {http.ClientRequest} req
179
- * @param {http.IncomingMessage} res
176
+ * @param {object} segment TraceSegment instance
177
+ * @param {string} hostname host of the HTTP request
178
+ * @param {object} req http.ClientRequest
179
+ * @param {object} res http.IncomingMessage
180
180
  */
181
181
  function handleResponse(segment, hostname, req, res) {
182
182
  // Add response attributes for spans
@@ -5,6 +5,8 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 42] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
8
10
  const shimmer = require('../../shimmer')
9
11
  const logger = require('../../logger').child({ component: 'http' })
10
12
  const recordWeb = require('../../metrics/recorders/http')
@@ -13,21 +15,20 @@ const cat = require('../../util/cat')
13
15
  const instrumentOutbound = require('./http-outbound')
14
16
  const url = require('url')
15
17
  const urltils = require('../../util/urltils')
16
- const properties = require('../../util/properties')
17
18
  const headerAttributes = require('../../header-attributes')
18
19
  const headerProcessing = require('../../header-processing')
19
20
 
20
21
  const NAMES = require('../../metrics/names')
21
22
  const DESTS = require('../../config/attribute-filter').DESTINATIONS
22
23
 
24
+ const symbols = require('../../symbols')
25
+
23
26
  /*
24
27
  *
25
28
  * CONSTANTS
26
29
  *
27
30
  */
28
- const NR_CONNECTION_PROP = '__NR__connection'
29
31
  const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
30
- const TRANSACTION_INFO_KEY = '__NR_transactionInfo'
31
32
 
32
33
  // For incoming requests this instrumentation functions by wrapping
33
34
  // `http.createServer` and `http.Server#addListener`. The former merely sets the
@@ -55,12 +56,6 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
55
56
  // Store the transaction information on the request and response.
56
57
  const txInfo = storeTxInfo(transaction, request, response)
57
58
 
58
- // Hook for web framework instrumentations that don't have easy access to
59
- // the request entry point.
60
- if (properties.hasOwn(this, '__NR_onRequestStarted')) {
61
- this.__NR_onRequestStarted(request, response)
62
- }
63
-
64
59
  if (request) {
65
60
  initializeRequest(transaction, request)
66
61
  }
@@ -204,7 +199,6 @@ function storeTxInfo(transaction, request, response) {
204
199
  logger.debug('Missing request or response object! Not storing transaction info.')
205
200
  return
206
201
  }
207
- const hideInternal = transaction.agent.config.transaction_tracer.hide_internals
208
202
 
209
203
  const txInfo = {
210
204
  transaction: transaction,
@@ -212,12 +206,7 @@ function storeTxInfo(transaction, request, response) {
212
206
  errorHandled: false,
213
207
  error: null
214
208
  }
215
- if (hideInternal) {
216
- properties.setInternal(request, TRANSACTION_INFO_KEY, txInfo)
217
- properties.setInternal(response, TRANSACTION_INFO_KEY, txInfo)
218
- } else {
219
- request[TRANSACTION_INFO_KEY] = response[TRANSACTION_INFO_KEY] = txInfo
220
- }
209
+ request[symbols.transactionInfo] = response[symbols.transactionInfo] = txInfo
221
210
 
222
211
  logger.trace('Stored transaction %s information on request and response', transaction.id)
223
212
 
@@ -245,7 +234,7 @@ function wrapResponseEnd(agent, proto) {
245
234
  }
246
235
 
247
236
  return function wrappedResEnd() {
248
- const txInfo = this && this[TRANSACTION_INFO_KEY]
237
+ const txInfo = this && this[symbols.transactionInfo]
249
238
  if (!txInfo) {
250
239
  return end.apply(this, arguments)
251
240
  }
@@ -256,10 +245,11 @@ function wrapResponseEnd(agent, proto) {
256
245
  }
257
246
 
258
247
  // If an error happened, add it to the aggregator.
259
- if (txInfo.error) {
260
- if (!txInfo.errorHandled || urltils.isError(agent.config, this.statusCode)) {
261
- agent.errors.add(txInfo.transaction, txInfo.error)
262
- }
248
+ if (
249
+ txInfo.error &&
250
+ (!txInfo.errorHandled || urltils.isError(agent.config, this.statusCode))
251
+ ) {
252
+ agent.errors.add(txInfo.transaction, txInfo.error)
263
253
  }
264
254
 
265
255
  // End all the segments leading up to and including this one.
@@ -393,9 +383,9 @@ function wrapRequest(agent, request) {
393
383
  const reqArgs = [options, cb]
394
384
 
395
385
  // Don't pollute metrics and calls with NR connections
396
- const internalOnly = options && options[NR_CONNECTION_PROP]
386
+ const internalOnly = options && options[symbols.offTheRecord]
397
387
  if (internalOnly) {
398
- delete options[NR_CONNECTION_PROP]
388
+ delete options[symbols.offTheRecord]
399
389
  }
400
390
 
401
391
  // If this is not a request we're recording, exit early.
@@ -492,8 +482,7 @@ module.exports = function initialize(agent, http, moduleName) {
492
482
  args[1] = agent.tracer.bindFunction(args[1], segment, true)
493
483
  }
494
484
 
495
- const sock = agent.tracer.bindFunction(original, segment, true).apply(this, args)
496
- return sock
485
+ return agent.tracer.bindFunction(original, segment, true).apply(this, args)
497
486
  }
498
487
  }
499
488
  )
@@ -507,7 +496,7 @@ module.exports = function initialize(agent, http, moduleName) {
507
496
  * @param {string} header - The raw X-NewRelic-Synthetics header
508
497
  * @param {string} encKey - Encoding key handed down from the server
509
498
  * @param {Array.<number>} trustedIds - Array of accounts to trust the header from.
510
- * @param {Transaction} transaction - Where the synthetics data is attached to.
499
+ * @param {object} transaction - Where the synthetics data is attached to.
511
500
  */
512
501
  function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
513
502
  const synthData = parseSyntheticsHeader(header, encKey, trustedIds)
@@ -525,7 +514,7 @@ function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
525
514
  * @param {string} header - The raw X-NewRelic-Synthetics header
526
515
  * @param {string} encKey - Encoding key handed down from the server
527
516
  * @param {Array.<number>} trustedIds - Array of accounts to trust the header from.
528
- * @return {Object|null} - On successful parse and verification an object of
517
+ * @returns {object | null} - On successful parse and verification an object of
529
518
  * synthetics data is returned, otherwise null is
530
519
  * returned.
531
520
  */
@@ -5,6 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 16] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
10
+ const symbols = require('../../symbols')
11
+
8
12
  module.exports = initialize
9
13
 
10
14
  function initialize(agent, timers, moduleName, shim) {
@@ -53,7 +57,7 @@ function initialize(agent, timers, moduleName, shim) {
53
57
  function wrapClearTimeout(shim, fn) {
54
58
  return function wrappedClearTimeout(timer) {
55
59
  if (timer && timer._onTimeout) {
56
- const segment = timer._onTimeout.__NR_segment
60
+ const segment = timer._onTimeout[symbols.segment]
57
61
  if (segment && !segment.opaque) {
58
62
  segment.ignore = true
59
63
  }
@@ -148,9 +148,7 @@ function wrapMiddleware(shim, middleware, name, route) {
148
148
  const segmentName = `onRequest/${name}`
149
149
  const spec = buildMiddlewareSpecForMiddlewareFunction(shim, segmentName, route)
150
150
 
151
- const newMiddlewareFunction = shim.recordMiddleware(middleware, spec)
152
-
153
- return newMiddlewareFunction
151
+ return shim.recordMiddleware(middleware, spec)
154
152
  }
155
153
 
156
154
  /**
@@ -78,8 +78,10 @@ function wrapStart(shim, original) {
78
78
  segment.addAttribute('grpc.statusCode', code)
79
79
  segment.addAttribute('grpc.statusText', details)
80
80
 
81
- if (code !== 0 && shim.agent.config.grpc.record_errors) {
82
- // this is currently just creating an error from the details string
81
+ const agent = shim.agent
82
+ const config = agent.config
83
+
84
+ if (shouldTrackError(code, config)) {
83
85
  shim.agent.errors.add(segment.transaction, details)
84
86
  }
85
87
 
@@ -184,9 +186,10 @@ function wrapRegister(shim, original) {
184
186
 
185
187
  function instrumentEventListeners(stream, transaction) {
186
188
  const agent = shim.agent
189
+ const config = agent.config
187
190
  stream.call.once('callEnd', (statusCode) => {
188
191
  transaction.trace.attributes.addAttribute(DESTINATION, 'response.status', statusCode)
189
- if (statusCode !== 0 && agent.config.grpc.record_errors) {
192
+ if (shouldTrackError(statusCode, config)) {
190
193
  const status = constants.Status[statusCode]
191
194
  const error = new Error(`gRPC status code ${statusCode}: ${status}`)
192
195
  agent.errors.add(transaction, error)
@@ -202,6 +205,14 @@ function wrapRegister(shim, original) {
202
205
  }
203
206
  }
204
207
 
208
+ function shouldTrackError(statusCode, config) {
209
+ return (
210
+ statusCode > 0 &&
211
+ config.grpc.record_errors &&
212
+ !config.grpc.ignore_status_codes.includes(statusCode)
213
+ )
214
+ }
215
+
205
216
  module.exports = function instrument(shim) {
206
217
  const genericShim = shim.makeSpecializedShim(shim.GENERIC, 'call-stream')
207
218
  const callStream = genericShim.require('./build/src/call-stream')
@@ -21,6 +21,11 @@ function wrapKeys(metacall) {
21
21
  * Thanks to Hernan Silberman!
22
22
  *
23
23
  * instrument the memcached driver to intercept calls and keep stats on them.
24
+ *
25
+ * @param agent
26
+ * @param memcached
27
+ * @param moduleName
28
+ * @param shim
24
29
  */
25
30
  module.exports = function initialize(agent, memcached, moduleName, shim) {
26
31
  const proto = memcached && memcached.prototype
@@ -4,6 +4,9 @@
4
4
  */
5
5
 
6
6
  'use strict'
7
+
8
+ /* eslint sonarjs/cognitive-complexity: ["error", 18] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
+
7
10
  const { CURSOR_OPS, COLLECTION_OPS, DB_OPS } = require('./constants')
8
11
  const common = module.exports
9
12
  common.NR_ATTRS = Symbol('NR_ATTRS')
@@ -11,7 +11,7 @@ const { captureAttributesOnStarted, makeQueryDescFunc } = require('./common')
11
11
  * parser used to grab the collection and operation
12
12
  * from a running query
13
13
  *
14
- * @param {Object} operation
14
+ * @param {object} operation
15
15
  */
16
16
  function queryParser(operation) {
17
17
  let collection = this.collectionName || 'unknown'
@@ -29,7 +29,7 @@ function queryParser(operation) {
29
29
  * add necessary attributes to segments
30
30
  *
31
31
  * @param {Shim} shim
32
- * @param {Object} mongodb resolved package
32
+ * @param {object} mongodb resolved package
33
33
  */
34
34
  module.exports = function instrument(shim, mongodb) {
35
35
  shim.setParser(queryParser)
@@ -65,6 +65,9 @@ module.exports = function instrument(shim, mongodb) {
65
65
  * Iterate over permutations and properly
66
66
  * wrap depending on the `recordDesc` above
67
67
  * See: https://github.com/mongodb/node-mongodb-native/blob/v3.0.5/lib/collection.js#L384
68
+ *
69
+ * @param _
70
+ * @param modules
68
71
  */
69
72
  function instrumentModules(_, modules) {
70
73
  modules.forEach((module) => {
@@ -80,7 +83,7 @@ module.exports = function instrument(shim, mongodb) {
80
83
  * if it needs to be wrapped as an operation or query
81
84
  *
82
85
  * @param {string} objectName name of class getting instrumented
83
- * @param {Object} object reference to the class getting instrumented
86
+ * @param {object} object reference to the class getting instrumented
84
87
  * @param {Define} meta describes the methods and if they are callbacks
85
88
  * promises, and return values
86
89
  */
@@ -25,7 +25,7 @@ module.exports = initialize
25
25
  * based on version of mongodb
26
26
  *
27
27
  * @param {Agent} agent
28
- * @param {Object} mongodb resolved package
28
+ * @param {object} mongodb resolved package
29
29
  * @param {string} moduleName name of module
30
30
  * @param {Shim} shim
31
31
  */