newrelic 8.3.0 → 8.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NEWS.md +76 -0
- package/README.md +7 -6
- package/THIRD_PARTY_NOTICES.md +95 -35
- 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 +1 -1
- 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 +12 -10
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +82 -66
- 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 +85 -24
- 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 +16 -5
- 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/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/serverless/aws-lambda.js +8 -2
- 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.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 -6
- package/stub_api.js +8 -8
|
@@ -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
|
-
}
|
|
@@ -26,9 +26,6 @@ const DESTS = require('../../config/attribute-filter').DESTINATIONS
|
|
|
26
26
|
*
|
|
27
27
|
*/
|
|
28
28
|
const NR_CONNECTION_PROP = '__NR__connection'
|
|
29
|
-
const NEWRELIC_ID_HEADER = 'x-newrelic-id'
|
|
30
|
-
const NEWRELIC_APP_DATA_HEADER = 'x-newrelic-app-data'
|
|
31
|
-
const NEWRELIC_TRANSACTION_HEADER = 'x-newrelic-transaction'
|
|
32
29
|
const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
|
|
33
30
|
const TRANSACTION_INFO_KEY = '__NR_transactionInfo'
|
|
34
31
|
|
|
@@ -47,7 +44,7 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
|
|
|
47
44
|
let serverPort = null
|
|
48
45
|
|
|
49
46
|
return tracer.transactionProxy(function wrappedHandler(evnt, request, response) {
|
|
50
|
-
|
|
47
|
+
const transaction = tracer.getTransaction()
|
|
51
48
|
if (!transaction) {
|
|
52
49
|
return emit.apply(this, arguments)
|
|
53
50
|
}
|
|
@@ -108,7 +105,7 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
|
|
|
108
105
|
|
|
109
106
|
// store the port on which this transaction runs
|
|
110
107
|
if (this.address instanceof Function) {
|
|
111
|
-
|
|
108
|
+
const address = this.address()
|
|
112
109
|
if (address) {
|
|
113
110
|
serverPort = address.port
|
|
114
111
|
}
|
|
@@ -142,15 +139,13 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
|
|
|
142
139
|
// Node http headers are automatically lowercase
|
|
143
140
|
transaction.acceptDistributedTraceHeaders(transport, request.headers)
|
|
144
141
|
} else if (agent.config.cross_application_tracer.enabled) {
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
}
|
|
142
|
+
const { id, transactionId } = cat.extractCatHeaders(request.headers)
|
|
143
|
+
const { externalId, externalTransaction } = cat.parseCatData(
|
|
144
|
+
id,
|
|
145
|
+
transactionId,
|
|
146
|
+
agent.config.encoding_key
|
|
147
|
+
)
|
|
148
|
+
cat.assignCatToTransaction(externalId, externalTransaction, transaction)
|
|
154
149
|
}
|
|
155
150
|
|
|
156
151
|
function instrumentedFinish() {
|
|
@@ -164,7 +159,7 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
|
|
|
164
159
|
|
|
165
160
|
if (response) {
|
|
166
161
|
if (response.statusCode != null) {
|
|
167
|
-
|
|
162
|
+
const responseCode = String(response.statusCode)
|
|
168
163
|
|
|
169
164
|
if (/^\d+$/.test(responseCode)) {
|
|
170
165
|
transaction.trace.attributes.addAttribute(
|
|
@@ -187,7 +182,7 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
|
|
|
187
182
|
segment.addSpanAttribute('http.statusText', response.statusMessage)
|
|
188
183
|
}
|
|
189
184
|
|
|
190
|
-
|
|
185
|
+
const headers = response.getHeaders()
|
|
191
186
|
if (headers) {
|
|
192
187
|
headerAttributes.collectResponseHeaders(headers, transaction)
|
|
193
188
|
}
|
|
@@ -209,9 +204,9 @@ function storeTxInfo(transaction, request, response) {
|
|
|
209
204
|
logger.debug('Missing request or response object! Not storing transaction info.')
|
|
210
205
|
return
|
|
211
206
|
}
|
|
212
|
-
|
|
207
|
+
const hideInternal = transaction.agent.config.transaction_tracer.hide_internals
|
|
213
208
|
|
|
214
|
-
|
|
209
|
+
const txInfo = {
|
|
215
210
|
transaction: transaction,
|
|
216
211
|
segmentStack: [],
|
|
217
212
|
errorHandled: false,
|
|
@@ -239,7 +234,7 @@ function initializeRequest(transaction, request) {
|
|
|
239
234
|
}
|
|
240
235
|
|
|
241
236
|
function wrapResponseEnd(agent, proto) {
|
|
242
|
-
|
|
237
|
+
const tracer = agent.tracer
|
|
243
238
|
|
|
244
239
|
// On end, we must freeze the current name state to maintain the route that
|
|
245
240
|
// responded and also end the current segment (otherwise it may become truncated).
|
|
@@ -250,7 +245,7 @@ function wrapResponseEnd(agent, proto) {
|
|
|
250
245
|
}
|
|
251
246
|
|
|
252
247
|
return function wrappedResEnd() {
|
|
253
|
-
|
|
248
|
+
const txInfo = this && this[TRANSACTION_INFO_KEY]
|
|
254
249
|
if (!txInfo) {
|
|
255
250
|
return end.apply(this, arguments)
|
|
256
251
|
}
|
|
@@ -268,10 +263,10 @@ function wrapResponseEnd(agent, proto) {
|
|
|
268
263
|
}
|
|
269
264
|
|
|
270
265
|
// End all the segments leading up to and including this one.
|
|
271
|
-
for (
|
|
266
|
+
for (let i = txInfo.segmentStack.length - 1; i >= 0; --i) {
|
|
272
267
|
txInfo.segmentStack[i].end()
|
|
273
268
|
}
|
|
274
|
-
|
|
269
|
+
const segment = tracer.getSegment()
|
|
275
270
|
if (segment) {
|
|
276
271
|
segment.end()
|
|
277
272
|
}
|
|
@@ -288,7 +283,7 @@ function wrapResponseEnd(agent, proto) {
|
|
|
288
283
|
// the shimmer stuff if you'd like to verify.
|
|
289
284
|
function wrapWriteHead(agent, writeHead) {
|
|
290
285
|
return function wrappedWriteHead() {
|
|
291
|
-
|
|
286
|
+
const transaction = agent.tracer.getTransaction()
|
|
292
287
|
if (!transaction) {
|
|
293
288
|
logger.trace('No transaction - not adding response CAT headers')
|
|
294
289
|
return writeHead.apply(this, arguments)
|
|
@@ -307,13 +302,7 @@ function wrapWriteHead(agent, writeHead) {
|
|
|
307
302
|
return writeHead.apply(this, arguments)
|
|
308
303
|
}
|
|
309
304
|
|
|
310
|
-
|
|
311
|
-
accountId = parseInt(accountId, 10)
|
|
312
|
-
if (agent.config.trusted_account_ids.indexOf(accountId) === -1) {
|
|
313
|
-
logger.trace(
|
|
314
|
-
'Request from untrusted account id: %s - not adding response CAT headers',
|
|
315
|
-
accountId
|
|
316
|
-
)
|
|
305
|
+
if (!cat.isTrustedAccountId(transaction.incomingCatId, agent.config.trusted_account_ids)) {
|
|
317
306
|
return writeHead.apply(this, arguments)
|
|
318
307
|
}
|
|
319
308
|
|
|
@@ -332,8 +321,8 @@ function wrapWriteHead(agent, writeHead) {
|
|
|
332
321
|
|
|
333
322
|
// -1 means no content length header was sent. We should only send this
|
|
334
323
|
// value in the appData if the header is set.
|
|
335
|
-
|
|
336
|
-
|
|
324
|
+
let contentLength = -1
|
|
325
|
+
const newHeaders = arguments[arguments.length - 1]
|
|
337
326
|
|
|
338
327
|
if (typeof newHeaders === 'object') {
|
|
339
328
|
contentLength = headerProcessing.getContentLengthFromHeaders(newHeaders)
|
|
@@ -347,33 +336,11 @@ function wrapWriteHead(agent, writeHead) {
|
|
|
347
336
|
// actual duration.
|
|
348
337
|
transaction.catResponseTime = transaction.timer.getDurationInMillis()
|
|
349
338
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
appData = JSON.stringify([
|
|
355
|
-
agent.config.cross_process_id, // cross_process_id
|
|
356
|
-
txName, // transaction name
|
|
357
|
-
transaction.queueTime / 1000, // queue time (s)
|
|
358
|
-
transaction.catResponseTime / 1000, // response time (s)
|
|
359
|
-
contentLength, // content length (if content-length header is also being sent)
|
|
360
|
-
transaction.id, // TransactionGuid
|
|
361
|
-
false // force a transaction trace to be recorded
|
|
362
|
-
])
|
|
363
|
-
} catch (err) {
|
|
364
|
-
logger.trace(
|
|
365
|
-
err,
|
|
366
|
-
'Failed to serialize transaction: %s - not adding CAT response headers',
|
|
367
|
-
txName
|
|
368
|
-
)
|
|
369
|
-
return writeHead.apply(this, arguments)
|
|
339
|
+
const { key, data } = cat.encodeAppData(agent.config, transaction, contentLength)
|
|
340
|
+
if (key && data) {
|
|
341
|
+
this.setHeader(key, data)
|
|
342
|
+
logger.trace('Added outbound response CAT headers in transaction %s', transaction.id)
|
|
370
343
|
}
|
|
371
|
-
|
|
372
|
-
var encKey = agent.config.encoding_key
|
|
373
|
-
var obfAppData = hashes.obfuscateNameUsingKey(appData, encKey)
|
|
374
|
-
this.setHeader(NEWRELIC_APP_DATA_HEADER, obfAppData)
|
|
375
|
-
logger.trace('Added outbound response CAT headers in transaction %s', transaction.id)
|
|
376
|
-
|
|
377
344
|
return writeHead.apply(this, arguments)
|
|
378
345
|
}
|
|
379
346
|
}
|
|
@@ -423,7 +390,7 @@ function wrapRequest(agent, request) {
|
|
|
423
390
|
options = Object.assign(input || {}, options)
|
|
424
391
|
}
|
|
425
392
|
|
|
426
|
-
|
|
393
|
+
const reqArgs = [options, cb]
|
|
427
394
|
|
|
428
395
|
// Don't pollute metrics and calls with NR connections
|
|
429
396
|
const internalOnly = options && options[NR_CONNECTION_PROP]
|
|
@@ -480,7 +447,7 @@ module.exports = function initialize(agent, http, moduleName) {
|
|
|
480
447
|
'http.Server.prototype',
|
|
481
448
|
'emit',
|
|
482
449
|
function wrapEmit(emit) {
|
|
483
|
-
|
|
450
|
+
const txStarter = wrapEmitWithTransaction(agent, emit, IS_HTTPS)
|
|
484
451
|
return function wrappedEmit(evnt) {
|
|
485
452
|
if (evnt === 'request') {
|
|
486
453
|
return txStarter.apply(this, arguments)
|
|
@@ -502,7 +469,7 @@ module.exports = function initialize(agent, http, moduleName) {
|
|
|
502
469
|
)
|
|
503
470
|
}
|
|
504
471
|
|
|
505
|
-
|
|
472
|
+
const agentProto = http && http.Agent && http.Agent.prototype
|
|
506
473
|
|
|
507
474
|
shimmer.wrapMethod(http, 'http', 'request', wrapRequest.bind(null, agent))
|
|
508
475
|
|
|
@@ -518,14 +485,14 @@ module.exports = function initialize(agent, http, moduleName) {
|
|
|
518
485
|
return original.apply(this, arguments)
|
|
519
486
|
}
|
|
520
487
|
|
|
521
|
-
|
|
488
|
+
const segment = agent.tracer.createSegment('http.Agent#createConnection')
|
|
522
489
|
|
|
523
|
-
|
|
490
|
+
const args = agent.tracer.slice(arguments)
|
|
524
491
|
if (typeof args[1] === 'function') {
|
|
525
492
|
args[1] = agent.tracer.bindFunction(args[1], segment, true)
|
|
526
493
|
}
|
|
527
494
|
|
|
528
|
-
|
|
495
|
+
const sock = agent.tracer.bindFunction(original, segment, true).apply(this, args)
|
|
529
496
|
return sock
|
|
530
497
|
}
|
|
531
498
|
}
|
|
@@ -543,7 +510,7 @@ module.exports = function initialize(agent, http, moduleName) {
|
|
|
543
510
|
* @param {Transaction} transaction - Where the synthetics data is attached to.
|
|
544
511
|
*/
|
|
545
512
|
function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
|
|
546
|
-
|
|
513
|
+
const synthData = parseSyntheticsHeader(header, encKey, trustedIds)
|
|
547
514
|
if (!synthData) {
|
|
548
515
|
return
|
|
549
516
|
}
|
|
@@ -565,14 +532,14 @@ function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
|
|
|
565
532
|
function parseSyntheticsHeader(header, encKey, trustedIds) {
|
|
566
533
|
// Eagerly declare this object because we know what it should look like and
|
|
567
534
|
// can use that for header verification.
|
|
568
|
-
|
|
535
|
+
const parsedData = {
|
|
569
536
|
version: null,
|
|
570
537
|
accountId: null,
|
|
571
538
|
resourceId: null,
|
|
572
539
|
jobId: null,
|
|
573
540
|
monitorId: null
|
|
574
541
|
}
|
|
575
|
-
|
|
542
|
+
let synthData = null
|
|
576
543
|
try {
|
|
577
544
|
synthData = JSON.parse(hashes.deobfuscateNameUsingKey(header, encKey))
|
|
578
545
|
} catch (e) {
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
module.exports = initialize
|
|
9
9
|
|
|
10
10
|
function initialize(agent, inspector, name, shim) {
|
|
11
|
-
|
|
11
|
+
const sessionProto = inspector && inspector.Session && inspector.Session.prototype
|
|
12
12
|
if (!sessionProto) {
|
|
13
13
|
return false
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
shim.wrap(sessionProto, 'post', function wrapPost(shim, fn) {
|
|
17
17
|
return function wrappedPost() {
|
|
18
|
-
|
|
18
|
+
const args = shim.argsToArray.apply(shim, arguments)
|
|
19
19
|
shim.bindCallbackSegment(args, shim.LAST)
|
|
20
20
|
return fn.apply(this, args)
|
|
21
21
|
}
|
|
@@ -18,9 +18,9 @@ function initialize(agent, timers, moduleName, shim) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// Manual copy because helper methods add significant overhead in some usages
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
for (
|
|
21
|
+
const len = arguments.length
|
|
22
|
+
const args = new Array(len)
|
|
23
|
+
for (let i = 0; i < len; ++i) {
|
|
24
24
|
args[i] = arguments[i]
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -70,7 +70,7 @@ function initialize(agent, timers, moduleName, shim) {
|
|
|
70
70
|
return function wrappedClearTimeout(timer) {
|
|
71
71
|
if (timer && timer._onTimeout) {
|
|
72
72
|
const segment = timer._onTimeout.__NR_segment
|
|
73
|
-
if (segment) {
|
|
73
|
+
if (segment && !segment.opaque) {
|
|
74
74
|
segment.ignore = true
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -85,9 +85,9 @@ function initialize(agent, timers, moduleName, shim) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
function makeWrappedPromisifyCompatible(shim, timers) {
|
|
88
|
-
const
|
|
89
|
-
Object.getOwnPropertySymbols(
|
|
90
|
-
timers.setTimeout[symbol] =
|
|
88
|
+
const originalSetTimeout = shim.getOriginal(timers.setTimeout)
|
|
89
|
+
Object.getOwnPropertySymbols(originalSetTimeout).forEach((symbol) => {
|
|
90
|
+
timers.setTimeout[symbol] = originalSetTimeout[symbol]
|
|
91
91
|
})
|
|
92
92
|
|
|
93
93
|
const originalSetInterval = shim.getOriginal(timers.setInterval)
|
|
@@ -9,13 +9,13 @@ const recorder = require('../../metrics/recorders/generic')
|
|
|
9
9
|
|
|
10
10
|
module.exports = initialize
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const methods = ['deflate', 'deflateRaw', 'gzip', 'gunzip', 'inflate', 'inflateRaw', 'unzip']
|
|
13
13
|
|
|
14
14
|
function initialize(agent, zlib, moduleName, shim) {
|
|
15
15
|
shim.record(zlib, methods, recordZLib)
|
|
16
16
|
|
|
17
17
|
if (zlib.Deflate && zlib.Deflate.prototype) {
|
|
18
|
-
|
|
18
|
+
const proto = Object.getPrototypeOf(zlib.Deflate.prototype)
|
|
19
19
|
if (proto._transform) {
|
|
20
20
|
// streams2
|
|
21
21
|
shim.wrap(proto, '_transform', wrapNoSegment)
|
|
@@ -12,8 +12,8 @@ module.exports = function initialize(agent, director, moduleName, shim) {
|
|
|
12
12
|
return route instanceof Array ? route.join('/') : route
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const methods = ['on', 'route']
|
|
16
|
+
const proto = director.Router.prototype
|
|
17
17
|
shim.wrapMiddlewareMounter(proto, methods, {
|
|
18
18
|
route: shim.SECOND,
|
|
19
19
|
wrapper: function wrapMiddleware(shim, middleware, name, path) {
|
|
@@ -32,7 +32,7 @@ module.exports = function initialize(agent, director, moduleName, shim) {
|
|
|
32
32
|
|
|
33
33
|
shim.wrap(proto, 'mount', function wrapMount(shim, mount) {
|
|
34
34
|
return function wrappedMount(routes, path) {
|
|
35
|
-
|
|
35
|
+
const isAsync = this.async
|
|
36
36
|
shim.wrap(routes, director.http.methods, function wrapRoute(shim, route) {
|
|
37
37
|
return shim.recordMiddleware(route, {
|
|
38
38
|
route: path.join('/'),
|
|
@@ -45,7 +45,7 @@ module.exports = function initialize(agent, director, moduleName, shim) {
|
|
|
45
45
|
next: isAsync ? shim.LAST : null
|
|
46
46
|
})
|
|
47
47
|
})
|
|
48
|
-
|
|
48
|
+
const args = [routes, path]
|
|
49
49
|
return mount.apply(this, args)
|
|
50
50
|
}
|
|
51
51
|
})
|
|
@@ -48,7 +48,7 @@ function wrapExpress4(shim, express) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
return function wrappedRoute() {
|
|
51
|
-
|
|
51
|
+
const route = fn.apply(this, arguments)
|
|
52
52
|
|
|
53
53
|
// Express should create a new route and layer every time Router#route is
|
|
54
54
|
// called, but just to be on the safe side, make sure we haven't wrapped
|
|
@@ -56,7 +56,7 @@ function wrapExpress4(shim, express) {
|
|
|
56
56
|
if (!shim.isWrapped(route, 'get')) {
|
|
57
57
|
wrapRouteMethods(shim, route, '')
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
const layer = this.stack[this.stack.length - 1]
|
|
60
60
|
|
|
61
61
|
// This wraps a 'done' function but not a traditional 'next' function. This allows
|
|
62
62
|
// the route to stay on the stack for middleware nesting after the router.
|
|
@@ -120,7 +120,7 @@ function wrapExpress3(shim, express) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
function wrapRouteMethods(shim, route, path) {
|
|
123
|
-
|
|
123
|
+
const methods = ['all', 'delete', 'get', 'head', 'opts', 'post', 'put', 'patch']
|
|
124
124
|
shim.wrapMiddlewareMounter(route, methods, { route: path, wrapper: wrapMiddleware })
|
|
125
125
|
}
|
|
126
126
|
|
|
@@ -128,13 +128,13 @@ function wrapResponse(shim, response) {
|
|
|
128
128
|
shim.recordRender(response, 'render', {
|
|
129
129
|
view: shim.FIRST,
|
|
130
130
|
callback: function bindCallback(shim, render, name, segment, args) {
|
|
131
|
-
|
|
131
|
+
let cbIdx = shim.normalizeIndex(args.length, shim.LAST)
|
|
132
132
|
if (cbIdx === null) {
|
|
133
133
|
return
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
const res = this
|
|
137
|
+
let cb = args[cbIdx]
|
|
138
138
|
if (!shim.isFunction(cb)) {
|
|
139
139
|
++cbIdx
|
|
140
140
|
cb = function defaultRenderCB(err, str) {
|
|
@@ -152,8 +152,8 @@ function wrapResponse(shim, response) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
function wrapMiddleware(shim, middleware, name, route) {
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
let method = null
|
|
156
|
+
const spec = {
|
|
157
157
|
route: route,
|
|
158
158
|
type: shim.MIDDLEWARE,
|
|
159
159
|
matchArity: true,
|