newrelic 8.2.0 → 8.5.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.
Files changed (138) hide show
  1. package/NEWS.md +5061 -4963
  2. package/README.md +7 -6
  3. package/THIRD_PARTY_NOTICES.md +95 -68
  4. package/api.js +74 -68
  5. package/bin/test-naming-rules.js +22 -22
  6. package/lib/agent.js +4 -4
  7. package/lib/attributes.js +2 -2
  8. package/lib/collector/api.js +12 -12
  9. package/lib/collector/facts.js +2 -3
  10. package/lib/collector/http-agents.js +12 -11
  11. package/lib/collector/key-parser.js +1 -1
  12. package/lib/collector/remote-method.js +27 -26
  13. package/lib/config/attribute-filter.js +23 -23
  14. package/lib/config/default.js +26 -9
  15. package/lib/config/env.js +14 -4
  16. package/lib/config/hsm.js +1 -1
  17. package/lib/config/index.js +90 -69
  18. package/lib/config/lasp.js +3 -3
  19. package/lib/config/merge-server-config.js +1 -1
  20. package/lib/db/parse-sql.js +8 -8
  21. package/lib/db/parsed-statement.js +9 -8
  22. package/lib/db/query-parsers/sql.js +7 -7
  23. package/lib/db/query-sample.js +9 -9
  24. package/lib/db/query-trace-aggregator.js +4 -4
  25. package/lib/db/statement-matcher.js +5 -5
  26. package/lib/db/utils.js +1 -1
  27. package/lib/environment.js +43 -43
  28. package/lib/errors/error-collector.js +2 -2
  29. package/lib/errors/error-trace-aggregator.js +1 -1
  30. package/lib/errors/helper.js +3 -3
  31. package/lib/errors/index.js +17 -17
  32. package/lib/feature_flags.js +7 -5
  33. package/lib/header-attributes.js +6 -6
  34. package/lib/header-processing.js +1 -1
  35. package/lib/instrumentation/amqplib.js +26 -26
  36. package/lib/instrumentation/bluebird.js +3 -3
  37. package/lib/instrumentation/cassandra-driver.js +7 -3
  38. package/lib/instrumentation/connect.js +4 -4
  39. package/lib/instrumentation/core/async_hooks.js +6 -6
  40. package/lib/instrumentation/core/domain.js +2 -2
  41. package/lib/instrumentation/core/globals.js +1 -1
  42. package/lib/instrumentation/core/http-outbound.js +15 -84
  43. package/lib/instrumentation/core/http.js +34 -67
  44. package/lib/instrumentation/core/inspector.js +2 -2
  45. package/lib/instrumentation/core/timers.js +7 -7
  46. package/lib/instrumentation/core/zlib.js +2 -2
  47. package/lib/instrumentation/director.js +4 -4
  48. package/lib/instrumentation/express.js +8 -8
  49. package/lib/instrumentation/fastify/spec-builders.js +57 -47
  50. package/lib/instrumentation/fastify.js +111 -28
  51. package/lib/instrumentation/generic-pool.js +1 -1
  52. package/lib/instrumentation/hapi/hapi-17.js +11 -11
  53. package/lib/instrumentation/hapi/shared.js +1 -1
  54. package/lib/instrumentation/hapi.js +22 -22
  55. package/lib/instrumentation/ioredis.js +7 -7
  56. package/lib/instrumentation/memcached.js +7 -7
  57. package/lib/instrumentation/mongodb/common.js +73 -23
  58. package/lib/instrumentation/mongodb/v3-mongo.js +20 -1
  59. package/lib/instrumentation/mongodb/v4-mongo.js +6 -7
  60. package/lib/instrumentation/mysql.js +19 -19
  61. package/lib/instrumentation/oracle.js +15 -15
  62. package/lib/instrumentation/pg.js +4 -4
  63. package/lib/instrumentation/promise.js +46 -46
  64. package/lib/instrumentation/q.js +2 -2
  65. package/lib/instrumentation/redis.js +11 -11
  66. package/lib/instrumentation/restify.js +1 -1
  67. package/lib/instrumentation/undici.js +242 -0
  68. package/lib/instrumentation/vision.js +4 -4
  69. package/lib/instrumentation/when.js +3 -3
  70. package/lib/instrumentations.js +2 -1
  71. package/lib/logger.js +5 -5
  72. package/lib/metrics/index.js +15 -15
  73. package/lib/metrics/mapper.js +7 -7
  74. package/lib/metrics/names.js +6 -3
  75. package/lib/metrics/normalizer/rule.js +9 -9
  76. package/lib/metrics/normalizer/tx_segment.js +17 -17
  77. package/lib/metrics/normalizer.js +22 -22
  78. package/lib/metrics/recorders/custom.js +5 -5
  79. package/lib/metrics/recorders/generic.js +3 -3
  80. package/lib/metrics/recorders/http.js +7 -7
  81. package/lib/metrics/recorders/http_external.js +7 -7
  82. package/lib/metrics/recorders/message-transaction.js +5 -6
  83. package/lib/metrics/recorders/other.js +5 -5
  84. package/lib/parse-proc-cpuinfo.js +25 -19
  85. package/lib/parse-proc-meminfo.js +8 -2
  86. package/lib/prioritized-attributes.js +2 -2
  87. package/lib/priority-queue.js +10 -10
  88. package/lib/reservoir.js +3 -3
  89. package/lib/sampler.js +26 -26
  90. package/lib/shim/datastore-shim.js +35 -32
  91. package/lib/shim/index.js +2 -2
  92. package/lib/shim/message-shim.js +47 -47
  93. package/lib/shim/promise-shim.js +1 -1
  94. package/lib/shim/shim.js +61 -61
  95. package/lib/shim/specs/index.js +3 -3
  96. package/lib/shim/transaction-shim.js +44 -192
  97. package/lib/shim/webframework-shim.js +52 -52
  98. package/lib/spans/span-event-aggregator.js +62 -10
  99. package/lib/spans/span-event.js +1 -1
  100. package/lib/spans/streaming-span-attributes.js +1 -1
  101. package/lib/stats/apdex.js +2 -2
  102. package/lib/stats/index.js +2 -2
  103. package/lib/system-info.js +23 -23
  104. package/lib/timer.js +5 -5
  105. package/lib/transaction/dt-payload.js +1 -1
  106. package/lib/transaction/index.js +40 -40
  107. package/lib/transaction/name-state.js +14 -14
  108. package/lib/transaction/trace/exclusive-time-calculator.js +6 -6
  109. package/lib/transaction/trace/index.js +14 -14
  110. package/lib/transaction/trace/segment.js +18 -18
  111. package/lib/transaction/tracecontext.js +1 -1
  112. package/lib/transaction/tracer/index.js +53 -49
  113. package/lib/uninstrumented.js +7 -7
  114. package/lib/util/arity.js +2 -2
  115. package/lib/util/byte-limit.js +4 -4
  116. package/lib/util/cat.js +269 -24
  117. package/lib/util/codec.js +2 -2
  118. package/lib/util/copy.js +2 -2
  119. package/lib/util/deep-equal.js +10 -10
  120. package/lib/util/flatten.js +4 -4
  121. package/lib/util/hashes.js +14 -14
  122. package/lib/util/label-parser.js +17 -17
  123. package/lib/util/logger.js +24 -24
  124. package/lib/util/process-version.js +2 -2
  125. package/lib/util/properties.js +4 -4
  126. package/lib/util/sql/obfuscate.js +15 -15
  127. package/lib/util/stream-sink.js +3 -3
  128. package/lib/util/unwrapped-core.js +2 -2
  129. package/lib/util/urltils.js +16 -16
  130. package/lib/utilization/aws-info.js +7 -7
  131. package/lib/utilization/azure-info.js +6 -6
  132. package/lib/utilization/common.js +13 -13
  133. package/lib/utilization/docker-info.js +11 -11
  134. package/lib/utilization/gcp-info.js +4 -4
  135. package/lib/utilization/index.js +5 -5
  136. package/lib/utilization/pcf-info.js +9 -9
  137. package/package.json +13 -7
  138. package/stub_api.js +8 -8
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- var url = require('url')
8
+ const url = require('url')
9
9
 
10
10
  // TODO: Make this an external module.
11
11
  // var newrelic = require('newrelic')
@@ -45,7 +45,7 @@ module.exports.selfRegister = function selfRegister(shimmer) {
45
45
  module.exports.instrumentPromiseAPI = instrumentChannelAPI
46
46
  module.exports.instrumentCallbackAPI = instrumentCallbackAPI
47
47
 
48
- var CHANNEL_METHODS = [
48
+ const CHANNEL_METHODS = [
49
49
  'close',
50
50
  'open',
51
51
  'assertQueue',
@@ -63,7 +63,7 @@ var CHANNEL_METHODS = [
63
63
  'recover'
64
64
  ]
65
65
 
66
- var TEMP_RE = /^amq\./
66
+ const TEMP_RE = /^amq\./
67
67
 
68
68
  function instrumentChannelAPI(shim, amqp) {
69
69
  instrumentAMQP(shim, amqp, true)
@@ -88,8 +88,8 @@ function instrumentAMQP(shim, amqp, promiseMode) {
88
88
  shim.setLibrary(shim.RABBITMQ)
89
89
 
90
90
  shim.record(amqp, 'connect', function recordConnect(shim, connect, name, args) {
91
- var connArgs = args[0]
92
- var params = null
91
+ let connArgs = args[0]
92
+ let params = null
93
93
 
94
94
  if (shim.isString(connArgs)) {
95
95
  connArgs = url.parse(connArgs)
@@ -114,13 +114,13 @@ function instrumentAMQP(shim, amqp, promiseMode) {
114
114
  }
115
115
 
116
116
  function wrapChannel(shim) {
117
- var libChannel = shim.require('./lib/channel')
117
+ const libChannel = shim.require('./lib/channel')
118
118
  if (!libChannel || !libChannel.Channel || !libChannel.Channel.prototype) {
119
119
  shim.logger.debug('Could not get Channel class to instrument.')
120
120
  return
121
121
  }
122
122
 
123
- var proto = libChannel.Channel.prototype
123
+ const proto = libChannel.Channel.prototype
124
124
  if (shim.isWrapped(proto.sendMessage)) {
125
125
  shim.logger.trace('Channel already instrumented.')
126
126
  return
@@ -133,15 +133,15 @@ function wrapChannel(shim) {
133
133
  }
134
134
 
135
135
  return function wrappedSendOrEnqueue() {
136
- var segment = shim.getSegment()
137
- var cb = arguments[arguments.length - 1]
136
+ const segment = shim.getSegment()
137
+ const cb = arguments[arguments.length - 1]
138
138
  if (!shim.isFunction(cb) || !segment) {
139
139
  shim.logger.debug({ cb: !!cb, segment: !!segment }, 'Not binding sendOrEnqueue callback')
140
140
  return fn.apply(this, arguments)
141
141
  }
142
142
 
143
143
  shim.logger.trace('Binding sendOrEnqueue callback to %s', segment.name)
144
- var args = shim.argsToArray.apply(shim, arguments)
144
+ const args = shim.argsToArray.apply(shim, arguments)
145
145
  args[args.length - 1] = shim.bindSegment(cb, segment)
146
146
  return fn.apply(this, args)
147
147
  }
@@ -170,11 +170,11 @@ function wrapChannel(shim) {
170
170
 
171
171
  shim.recordProduce(proto, 'sendMessage', recordSendMessage)
172
172
  function recordSendMessage(shim, fn, n, args) {
173
- var fields = args[0]
173
+ const fields = args[0]
174
174
  if (!fields) {
175
175
  return null
176
176
  }
177
- var isDefault = fields.exchange === ''
177
+ const isDefault = fields.exchange === ''
178
178
  let exchange = 'Default'
179
179
  if (!isDefault) {
180
180
  exchange = TEMP_RE.test(fields.exchange) ? null : fields.exchange
@@ -205,12 +205,12 @@ function getParameters(parameters, fields) {
205
205
  }
206
206
 
207
207
  function wrapPromiseChannel(shim) {
208
- var libPModel = shim.require('./lib/channel_model')
208
+ const libPModel = shim.require('./lib/channel_model')
209
209
  if (!libPModel || !libPModel.Channel || !libPModel.Channel.prototype) {
210
210
  shim.logger.debug('Could not get promise model Channel to instrument')
211
211
  }
212
212
 
213
- var proto = libPModel.Channel.prototype
213
+ const proto = libPModel.Channel.prototype
214
214
  if (shim.isWrapped(proto.consume)) {
215
215
  shim.logger.trace('Promise model already isntrumented.')
216
216
  return
@@ -231,11 +231,11 @@ function wrapPromiseChannel(shim) {
231
231
  shim.logger.trace('No results from consume.')
232
232
  return null
233
233
  }
234
- var parameters = Object.create(null)
234
+ const parameters = Object.create(null)
235
235
  getParameters(parameters, message.fields)
236
236
  getParameters(parameters, message.properties)
237
237
 
238
- var headers = null
238
+ let headers = null
239
239
  if (message.properties && message.properties.headers) {
240
240
  headers = message.properties.headers
241
241
  }
@@ -245,7 +245,7 @@ function wrapPromiseChannel(shim) {
245
245
  })
246
246
 
247
247
  shim.recordPurgeQueue(proto, 'purgeQueue', function recordPurge(shim, fn, name, args) {
248
- var queue = args[0] || null
248
+ let queue = args[0] || null
249
249
  if (TEMP_RE.test(queue)) {
250
250
  queue = null
251
251
  }
@@ -263,13 +263,13 @@ function wrapPromiseChannel(shim) {
263
263
  }
264
264
 
265
265
  function wrapCallbackChannel(shim) {
266
- var libCbModel = shim.require('./lib/callback_model')
266
+ const libCbModel = shim.require('./lib/callback_model')
267
267
  if (!libCbModel || !libCbModel.Channel || !libCbModel.Channel.prototype) {
268
268
  shim.logger.debug('Could not get callback model Channel to instrument')
269
269
  return
270
270
  }
271
271
 
272
- var proto = libCbModel.Channel.prototype
272
+ const proto = libCbModel.Channel.prototype
273
273
  if (shim.isWrapped(proto.consume)) {
274
274
  return
275
275
  }
@@ -309,16 +309,16 @@ function wrapCallbackChannel(shim) {
309
309
  destinationName: shim.FIRST,
310
310
  callback: shim.LAST,
311
311
  messageHandler: function handleConsumedMessage(shim, fn, name, args) {
312
- var message = args[1]
312
+ const message = args[1]
313
313
  if (!message) {
314
314
  shim.logger.trace('No results from consume.')
315
315
  return null
316
316
  }
317
- var parameters = Object.create(null)
317
+ const parameters = Object.create(null)
318
318
  getParameters(parameters, message.fields)
319
319
  getParameters(parameters, message.properties)
320
320
 
321
- var headers = null
321
+ let headers = null
322
322
  if (message.properties && message.properties.headers) {
323
323
  headers = message.properties.headers
324
324
  }
@@ -328,7 +328,7 @@ function wrapCallbackChannel(shim) {
328
328
  })
329
329
 
330
330
  shim.recordPurgeQueue(proto, 'purgeQueue', function recordPurge(shim, fn, name, args) {
331
- var queue = args[0]
331
+ let queue = args[0]
332
332
  if (TEMP_RE.test(queue)) {
333
333
  queue = null
334
334
  }
@@ -347,14 +347,14 @@ function wrapCallbackChannel(shim) {
347
347
  }
348
348
 
349
349
  function describeMessage(shim, consumer, name, args) {
350
- var message = args[0]
350
+ const message = args[0]
351
351
  if (!message || !message.properties) {
352
352
  shim.logger.debug({ message: message }, 'Failed to find message in consume arguments.')
353
353
  return null
354
354
  }
355
355
 
356
- var exchangeName = message.fields.exchange
357
- var parameters = getParameters(Object.create(null), message.fields)
356
+ let exchangeName = message.fields.exchange
357
+ const parameters = getParameters(Object.create(null), message.fields)
358
358
  getParameters(parameters, message.properties)
359
359
 
360
360
  if (!exchangeName) {
@@ -93,16 +93,16 @@ module.exports = function initialize(agent, bluebird, moduleName, shim) {
93
93
  shim.wrap(bluebird.Promise, 'getNewLibraryCopy', function wrapNewCopy(shim, original) {
94
94
  return function wrappedNewCopy() {
95
95
  shim.logger.trace('Instrumenting new library copy...')
96
- var copy = original.apply(this, arguments)
96
+ const copy = original.apply(this, arguments)
97
97
  module.exports(agent, copy, moduleName, shim)
98
98
  return copy
99
99
  }
100
100
  })
101
101
 
102
102
  // Need to copy over `coroutine.addYieldHandler`
103
- var coroutine = Promise && Promise.coroutine
103
+ const coroutine = Promise && Promise.coroutine
104
104
  if (shim.isWrapped(coroutine)) {
105
- var original = shim.getOriginal(coroutine)
105
+ const original = shim.getOriginal(coroutine)
106
106
  coroutine.addYieldHandler = original && original.addYieldHandler
107
107
  }
108
108
  }
@@ -6,10 +6,14 @@
6
6
  'use strict'
7
7
 
8
8
  module.exports = function initialize(agent, cassandra, moduleName, shim) {
9
- var proto = cassandra.Client.prototype
9
+ const proto = cassandra.Client.prototype
10
10
  shim.setDatastore(shim.CASSANDRA)
11
11
  shim.recordOperation(proto, ['connect', 'shutdown'], { callback: shim.LAST })
12
- shim.recordQuery(proto, '_innerExecute', { query: shim.FIRST, callback: shim.LAST })
12
+ if (proto._innerExecute) {
13
+ shim.recordQuery(proto, '_innerExecute', { query: shim.FIRST, callback: shim.LAST })
14
+ } else {
15
+ shim.recordQuery(proto, '_execute', { query: shim.FIRST, callback: shim.LAST })
16
+ }
13
17
  shim.recordBatchQuery(proto, 'batch', {
14
18
  query: findBatchQueryArg,
15
19
  callback: shim.LAST
@@ -23,6 +27,6 @@ module.exports = function initialize(agent, cassandra, moduleName, shim) {
23
27
  * @return {string} The query for this batch request.
24
28
  */
25
29
  function findBatchQueryArg(shim, batch, fnName, args) {
26
- var sql = (args[0] && args[0][0]) || ''
30
+ const sql = (args[0] && args[0][0]) || ''
27
31
  return sql.query || sql
28
32
  }
@@ -17,7 +17,7 @@ module.exports = function initialize(agent, connect, moduleName, shim) {
17
17
  return route
18
18
  })
19
19
 
20
- var proto =
20
+ const proto =
21
21
  (connect && connect.HTTPServer && connect.HTTPServer.prototype) || // v1
22
22
  (connect && connect.proto) // v2
23
23
 
@@ -31,7 +31,7 @@ module.exports = function initialize(agent, connect, moduleName, shim) {
31
31
  }
32
32
 
33
33
  function wrapMiddleware(shim, middleware, name, route) {
34
- var spec = {
34
+ const spec = {
35
35
  matchArity: true,
36
36
  route: route,
37
37
  type: shim.MIDDLEWARE,
@@ -56,9 +56,9 @@ function wrapMiddleware(shim, middleware, name, route) {
56
56
 
57
57
  function wrapConnectExport(shim, connect, v3) {
58
58
  shim.wrapExport(connect, function wrapExport(shim, fn) {
59
- var wrapper = shim.wrap(fn, function wrapConnect(shim, _fn) {
59
+ const wrapper = shim.wrap(fn, function wrapConnect(shim, _fn) {
60
60
  return function wrappedConnect() {
61
- var res = _fn.apply(this, arguments)
61
+ const res = _fn.apply(this, arguments)
62
62
  if (v3) {
63
63
  shim.wrapMiddlewareMounter(res, 'use', {
64
64
  route: shim.FIRST,
@@ -5,16 +5,16 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- var logger = require('../../logger').child({ component: 'async_hooks' })
9
- var promInit = require('../promise')
8
+ const logger = require('../../logger').child({ component: 'async_hooks' })
9
+ const promInit = require('../promise')
10
10
 
11
11
  module.exports = initialize
12
12
 
13
13
  /**
14
14
  * The spec for the native `Promise` class.
15
15
  */
16
- var STATIC_PROMISE_METHODS = ['accept', 'all', 'defer', 'race', 'reject', 'resolve']
17
- var NATIVE_PROMISE_SPEC = {
16
+ const STATIC_PROMISE_METHODS = ['accept', 'all', 'defer', 'race', 'reject', 'resolve']
17
+ const NATIVE_PROMISE_SPEC = {
18
18
  name: 'global',
19
19
  constructor: 'Promise',
20
20
  executor: true,
@@ -30,7 +30,7 @@ var NATIVE_PROMISE_SPEC = {
30
30
  }
31
31
 
32
32
  function initialize(agent, shim) {
33
- var enableHooks = agent.config.checkAsyncHookStatus()
33
+ const enableHooks = agent.config.checkAsyncHookStatus()
34
34
  if (enableHooks && tryAsyncHooks(agent, shim)) {
35
35
  logger.debug('Using async_hooks.')
36
36
  } else {
@@ -134,7 +134,7 @@ function getPromiseResolveStyleHooks(segmentMap, agent, shim) {
134
134
  return
135
135
  }
136
136
 
137
- let parentSegment = segmentMap.get(triggerId)
137
+ const parentSegment = segmentMap.get(triggerId)
138
138
 
139
139
  if (parentSegment && !parentSegment.transaction.isActive()) {
140
140
  // Stop propagating if the transaction was ended.
@@ -8,12 +8,12 @@
8
8
  module.exports = initialize
9
9
 
10
10
  function initialize(agent, domain, name, shim) {
11
- var proto = domain.Domain.prototype
11
+ const proto = domain.Domain.prototype
12
12
  shim.wrap(proto, 'emit', wrapEmit)
13
13
 
14
14
  function wrapEmit(shim, original) {
15
15
  return function wrappedEmit(ev) {
16
- var shouldRestoreContext =
16
+ const shouldRestoreContext =
17
17
  ev === 'error' && shim.getActiveSegment() === null && shim.getSegment(this)
18
18
 
19
19
  if (!shouldRestoreContext) {
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- var asyncHooks = require('./async_hooks')
8
+ const asyncHooks = require('./async_hooks')
9
9
 
10
10
  module.exports = initialize
11
11
 
@@ -5,13 +5,13 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- var recordExternal = require('../../metrics/recorders/http_external')
9
- var urltils = require('../../util/urltils')
10
- var hashes = require('../../util/hashes')
11
- var logger = require('../../logger').child({ component: 'outbound' })
12
- var shimmer = require('../../shimmer')
13
- var url = require('url')
14
- var copy = require('../../util/copy')
8
+ const recordExternal = require('../../metrics/recorders/http_external')
9
+ const cat = require('../../util/cat')
10
+ const urltils = require('../../util/urltils')
11
+ const logger = require('../../logger').child({ component: 'outbound' })
12
+ const shimmer = require('../../shimmer')
13
+ const url = require('url')
14
+ const copy = require('../../util/copy')
15
15
 
16
16
  const NAMES = require('../../metrics/names')
17
17
  const SHIM_SYMBOLS = require('../../shim/constants').SYMBOLS
@@ -20,8 +20,6 @@ const DEFAULT_HOST = 'localhost'
20
20
  const DEFAULT_PORT = 80
21
21
  const DEFAULT_SSL_PORT = 443
22
22
 
23
- const NEWRELIC_ID_HEADER = 'x-newrelic-id'
24
- const NEWRELIC_TRANSACTION_HEADER = 'x-newrelic-transaction'
25
23
  const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
26
24
 
27
25
  /**
@@ -96,13 +94,9 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
96
94
  transaction.insertDistributedTraceHeaders(outboundHeaders)
97
95
  }
98
96
  } else if (agent.config.cross_application_tracer.enabled) {
99
- if (agent.config.encoding_key) {
100
- _addCATHeaders(agent, transaction, outboundHeaders)
101
- } else {
102
- logger.trace('No encoding key found, not adding CAT headers')
103
- }
97
+ cat.addCatHeaders(agent.config, transaction, outboundHeaders)
104
98
  } else {
105
- logger.trace('CAT disabled, not adding headers!')
99
+ logger.trace('Both DT and CAT are disabled, not adding headers!')
106
100
  }
107
101
 
108
102
  if (Array.isArray(opts.headers)) {
@@ -129,7 +123,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
129
123
  if (parsed.parameters) {
130
124
  // Scrub and parse returns on object with a null prototype.
131
125
  // eslint-disable-next-line guard-for-in
132
- for (let key in parsed.parameters) {
126
+ for (const key in parsed.parameters) {
133
127
  segment.addSpanAttribute(`request.parameters.${key}`, parsed.parameters[key])
134
128
  }
135
129
  }
@@ -196,12 +190,14 @@ function handleResponse(segment, hostname, req, res) {
196
190
  // If CAT is enabled, grab those headers!
197
191
  const agent = segment.transaction.agent
198
192
  if (agent.config.cross_application_tracer.enabled && !agent.config.distributed_tracing.enabled) {
199
- pullCatHeaders(agent.config, segment, hostname, res.headers['x-newrelic-app-data'])
193
+ const { appData } = cat.extractCatHeaders(res.headers)
194
+ const decodedAppData = cat.parseAppData(agent.config, appData)
195
+ cat.assignCatToSegment(decodedAppData, segment, hostname)
200
196
  }
201
197
 
202
198
  // Again a custom emit wrapper because we want to watch for the `end` event.
203
199
  shimmer.wrapMethod(res, 'response', 'emit', function wrapEmit(emit) {
204
- var boundEmit = agent.tracer.bindFunction(emit, segment)
200
+ const boundEmit = agent.tracer.bindFunction(emit, segment)
205
201
  return function wrappedResponseEmit(evnt) {
206
202
  if (evnt === 'end') {
207
203
  segment.end()
@@ -212,77 +208,12 @@ function handleResponse(segment, hostname, req, res) {
212
208
  _makeNonEnumerable(res, 'emit')
213
209
  }
214
210
 
215
- function pullCatHeaders(config, segment, host, obfAppData) {
216
- if (!config.encoding_key) {
217
- logger.trace('config.encoding_key is not set - not parsing response CAT headers')
218
- return
219
- }
220
-
221
- if (!config.trusted_account_ids) {
222
- logger.trace('config.trusted_account_ids is not set - not parsing response CAT headers')
223
- return
224
- }
225
-
226
- // is our downstream request CAT-aware?
227
- if (!obfAppData) {
228
- logger.trace('Got no CAT app data in response header x-newrelic-app-data')
229
- } else {
230
- var appData = null
231
- try {
232
- appData = JSON.parse(hashes.deobfuscateNameUsingKey(obfAppData, config.encoding_key))
233
- } catch (e) {
234
- logger.warn('Got an unparsable CAT header x-newrelic-app-data: %s', obfAppData)
235
- return
236
- }
237
- // Make sure it is a trusted account
238
- if (appData.length && typeof appData[0] === 'string') {
239
- var accountId = appData[0].split('#')[0]
240
- accountId = parseInt(accountId, 10)
241
- if (config.trusted_account_ids.indexOf(accountId) === -1) {
242
- logger.trace('Response from untrusted CAT header account id: %s', accountId)
243
- } else {
244
- segment.catId = appData[0]
245
- segment.catTransaction = appData[1]
246
- segment.name =
247
- NAMES.EXTERNAL.TRANSACTION + host + '/' + segment.catId + '/' + segment.catTransaction
248
- if (appData.length >= 6) {
249
- segment.addAttribute('transaction_guid', appData[5])
250
- }
251
- logger.trace('Got inbound response CAT headers in transaction %s', segment.transaction.id)
252
- }
253
- }
254
- }
255
- }
256
-
257
211
  function _makeNonEnumerable(obj, prop) {
258
212
  try {
259
- var desc = Object.getOwnPropertyDescriptor(obj, prop)
213
+ const desc = Object.getOwnPropertyDescriptor(obj, prop)
260
214
  desc.enumerable = false
261
215
  Object.defineProperty(obj, prop, desc)
262
216
  } catch (e) {
263
217
  logger.debug(e, 'Failed to make %s non enumerable.', prop)
264
218
  }
265
219
  }
266
-
267
- function _addCATHeaders(agent, tx, outboundHeaders) {
268
- if (agent.config.obfuscatedId) {
269
- outboundHeaders[NEWRELIC_ID_HEADER] = agent.config.obfuscatedId
270
- }
271
-
272
- var pathHash = hashes.calculatePathHash(
273
- agent.config.applications()[0],
274
- tx.getFullName() || '',
275
- tx.referringPathHash
276
- )
277
- tx.pushPathHash(pathHash)
278
-
279
- try {
280
- let txData = JSON.stringify([tx.id, false, tx.tripId || tx.id, pathHash])
281
- txData = hashes.obfuscateNameUsingKey(txData, agent.config.encoding_key)
282
- outboundHeaders[NEWRELIC_TRANSACTION_HEADER] = txData
283
-
284
- logger.trace('Added outbound request CAT headers in transaction %s', tx.id)
285
- } catch (err) {
286
- logger.trace(err, 'Failed to create CAT payload')
287
- }
288
- }