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.
- package/NEWS.md +5061 -4963
- package/README.md +7 -6
- package/THIRD_PARTY_NOTICES.md +95 -68
- package/api.js +74 -68
- package/bin/test-naming-rules.js +22 -22
- package/lib/agent.js +4 -4
- package/lib/attributes.js +2 -2
- package/lib/collector/api.js +12 -12
- package/lib/collector/facts.js +2 -3
- package/lib/collector/http-agents.js +12 -11
- package/lib/collector/key-parser.js +1 -1
- package/lib/collector/remote-method.js +27 -26
- package/lib/config/attribute-filter.js +23 -23
- package/lib/config/default.js +26 -9
- package/lib/config/env.js +14 -4
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +90 -69
- package/lib/config/lasp.js +3 -3
- package/lib/config/merge-server-config.js +1 -1
- package/lib/db/parse-sql.js +8 -8
- package/lib/db/parsed-statement.js +9 -8
- package/lib/db/query-parsers/sql.js +7 -7
- package/lib/db/query-sample.js +9 -9
- package/lib/db/query-trace-aggregator.js +4 -4
- package/lib/db/statement-matcher.js +5 -5
- package/lib/db/utils.js +1 -1
- package/lib/environment.js +43 -43
- package/lib/errors/error-collector.js +2 -2
- package/lib/errors/error-trace-aggregator.js +1 -1
- package/lib/errors/helper.js +3 -3
- package/lib/errors/index.js +17 -17
- package/lib/feature_flags.js +7 -5
- package/lib/header-attributes.js +6 -6
- package/lib/header-processing.js +1 -1
- package/lib/instrumentation/amqplib.js +26 -26
- package/lib/instrumentation/bluebird.js +3 -3
- package/lib/instrumentation/cassandra-driver.js +7 -3
- package/lib/instrumentation/connect.js +4 -4
- package/lib/instrumentation/core/async_hooks.js +6 -6
- package/lib/instrumentation/core/domain.js +2 -2
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +15 -84
- package/lib/instrumentation/core/http.js +34 -67
- package/lib/instrumentation/core/inspector.js +2 -2
- package/lib/instrumentation/core/timers.js +7 -7
- package/lib/instrumentation/core/zlib.js +2 -2
- package/lib/instrumentation/director.js +4 -4
- package/lib/instrumentation/express.js +8 -8
- package/lib/instrumentation/fastify/spec-builders.js +57 -47
- package/lib/instrumentation/fastify.js +111 -28
- package/lib/instrumentation/generic-pool.js +1 -1
- package/lib/instrumentation/hapi/hapi-17.js +11 -11
- package/lib/instrumentation/hapi/shared.js +1 -1
- package/lib/instrumentation/hapi.js +22 -22
- package/lib/instrumentation/ioredis.js +7 -7
- package/lib/instrumentation/memcached.js +7 -7
- package/lib/instrumentation/mongodb/common.js +73 -23
- package/lib/instrumentation/mongodb/v3-mongo.js +20 -1
- package/lib/instrumentation/mongodb/v4-mongo.js +6 -7
- package/lib/instrumentation/mysql.js +19 -19
- package/lib/instrumentation/oracle.js +15 -15
- package/lib/instrumentation/pg.js +4 -4
- package/lib/instrumentation/promise.js +46 -46
- package/lib/instrumentation/q.js +2 -2
- package/lib/instrumentation/redis.js +11 -11
- package/lib/instrumentation/restify.js +1 -1
- package/lib/instrumentation/undici.js +242 -0
- package/lib/instrumentation/vision.js +4 -4
- package/lib/instrumentation/when.js +3 -3
- package/lib/instrumentations.js +2 -1
- package/lib/logger.js +5 -5
- package/lib/metrics/index.js +15 -15
- package/lib/metrics/mapper.js +7 -7
- package/lib/metrics/names.js +6 -3
- package/lib/metrics/normalizer/rule.js +9 -9
- package/lib/metrics/normalizer/tx_segment.js +17 -17
- package/lib/metrics/normalizer.js +22 -22
- package/lib/metrics/recorders/custom.js +5 -5
- package/lib/metrics/recorders/generic.js +3 -3
- package/lib/metrics/recorders/http.js +7 -7
- package/lib/metrics/recorders/http_external.js +7 -7
- package/lib/metrics/recorders/message-transaction.js +5 -6
- package/lib/metrics/recorders/other.js +5 -5
- package/lib/parse-proc-cpuinfo.js +25 -19
- package/lib/parse-proc-meminfo.js +8 -2
- package/lib/prioritized-attributes.js +2 -2
- package/lib/priority-queue.js +10 -10
- package/lib/reservoir.js +3 -3
- package/lib/sampler.js +26 -26
- package/lib/shim/datastore-shim.js +35 -32
- package/lib/shim/index.js +2 -2
- package/lib/shim/message-shim.js +47 -47
- package/lib/shim/promise-shim.js +1 -1
- package/lib/shim/shim.js +61 -61
- package/lib/shim/specs/index.js +3 -3
- package/lib/shim/transaction-shim.js +44 -192
- package/lib/shim/webframework-shim.js +52 -52
- package/lib/spans/span-event-aggregator.js +62 -10
- package/lib/spans/span-event.js +1 -1
- package/lib/spans/streaming-span-attributes.js +1 -1
- package/lib/stats/apdex.js +2 -2
- package/lib/stats/index.js +2 -2
- package/lib/system-info.js +23 -23
- package/lib/timer.js +5 -5
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/index.js +40 -40
- package/lib/transaction/name-state.js +14 -14
- package/lib/transaction/trace/exclusive-time-calculator.js +6 -6
- package/lib/transaction/trace/index.js +14 -14
- package/lib/transaction/trace/segment.js +18 -18
- package/lib/transaction/tracecontext.js +1 -1
- package/lib/transaction/tracer/index.js +53 -49
- package/lib/uninstrumented.js +7 -7
- package/lib/util/arity.js +2 -2
- package/lib/util/byte-limit.js +4 -4
- package/lib/util/cat.js +269 -24
- package/lib/util/codec.js +2 -2
- package/lib/util/copy.js +2 -2
- package/lib/util/deep-equal.js +10 -10
- package/lib/util/flatten.js +4 -4
- package/lib/util/hashes.js +14 -14
- package/lib/util/label-parser.js +17 -17
- package/lib/util/logger.js +24 -24
- package/lib/util/process-version.js +2 -2
- package/lib/util/properties.js +4 -4
- package/lib/util/sql/obfuscate.js +15 -15
- package/lib/util/stream-sink.js +3 -3
- package/lib/util/unwrapped-core.js +2 -2
- package/lib/util/urltils.js +16 -16
- package/lib/utilization/aws-info.js +7 -7
- package/lib/utilization/azure-info.js +6 -6
- package/lib/utilization/common.js +13 -13
- package/lib/utilization/docker-info.js +11 -11
- package/lib/utilization/gcp-info.js +4 -4
- package/lib/utilization/index.js +5 -5
- package/lib/utilization/pcf-info.js +9 -9
- package/package.json +13 -7
- package/stub_api.js +8 -8
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
-
|
|
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
|
-
|
|
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
|
-
|
|
173
|
+
const fields = args[0]
|
|
174
174
|
if (!fields) {
|
|
175
175
|
return null
|
|
176
176
|
}
|
|
177
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
234
|
+
const parameters = Object.create(null)
|
|
235
235
|
getParameters(parameters, message.fields)
|
|
236
236
|
getParameters(parameters, message.properties)
|
|
237
237
|
|
|
238
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
317
|
+
const parameters = Object.create(null)
|
|
318
318
|
getParameters(parameters, message.fields)
|
|
319
319
|
getParameters(parameters, message.properties)
|
|
320
320
|
|
|
321
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
357
|
-
|
|
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
|
-
|
|
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
|
-
|
|
103
|
+
const coroutine = Promise && Promise.coroutine
|
|
104
104
|
if (shim.isWrapped(coroutine)) {
|
|
105
|
-
|
|
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
|
-
|
|
9
|
+
const proto = cassandra.Client.prototype
|
|
10
10
|
shim.setDatastore(shim.CASSANDRA)
|
|
11
11
|
shim.recordOperation(proto, ['connect', 'shutdown'], { callback: shim.LAST })
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
59
|
+
const wrapper = shim.wrap(fn, function wrapConnect(shim, _fn) {
|
|
60
60
|
return function wrappedConnect() {
|
|
61
|
-
|
|
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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
16
|
+
const shouldRestoreContext =
|
|
17
17
|
ev === 'error' && shim.getActiveSegment() === null && shim.getSegment(this)
|
|
18
18
|
|
|
19
19
|
if (!shouldRestoreContext) {
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}
|