newrelic 6.3.0 → 6.5.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.
- package/{.eslintrc → .eslintrc.js} +4 -2
- package/.travis.yml +0 -1
- package/NEWS.md +136 -0
- package/README.md +1 -0
- package/api.js +75 -4
- package/bin/publish-docs.sh +1 -1
- package/bin/travis-node.sh +4 -1
- package/index.js +3 -3
- package/lib/aggregators/base-aggregator.js +1 -1
- package/lib/attributes.js +15 -6
- package/lib/config/default.js +11 -1
- package/lib/config/env.js +3 -1
- package/lib/config/hsm.js +6 -1
- package/lib/config/index.js +29 -8
- package/lib/config/lasp.js +16 -1
- package/lib/errors/error-collector.js +51 -90
- package/lib/errors/helper.js +13 -13
- package/lib/errors/index.js +36 -18
- package/lib/feature_flags.js +3 -3
- package/lib/header-processing.js +75 -0
- package/lib/instrumentation/core/child_process.js +12 -0
- package/lib/instrumentation/core/http-outbound.js +6 -28
- package/lib/instrumentation/core/http.js +100 -170
- package/lib/instrumentation/hapi/hapi-17.js +10 -3
- package/lib/metrics/names.js +1 -0
- package/lib/serverless/aws-lambda.js +79 -33
- package/lib/serverless/event-sources.json +128 -0
- package/lib/shim/transaction-shim.js +10 -33
- package/lib/spans/span-event-aggregator.js +2 -2
- package/lib/spans/span-event.js +33 -11
- package/lib/transaction/handle.js +73 -4
- package/lib/transaction/index.js +182 -34
- package/lib/transaction/trace/index.js +6 -5
- package/lib/transaction/trace/segment.js +12 -1
- package/lib/transaction/tracecontext.js +409 -163
- package/lib/util/get.js +16 -0
- package/lib/util/hashes.js +55 -6
- package/package.json +8 -10
- package/stub_api.js +5 -0
|
@@ -4,6 +4,7 @@ const errorsModule = require('./index')
|
|
|
4
4
|
|
|
5
5
|
const logger = require('../logger').child({component: 'error_tracer'})
|
|
6
6
|
const urltils = require('../util/urltils')
|
|
7
|
+
const Exception = require('../errors').Exception
|
|
7
8
|
const errorHelper = require('./helper')
|
|
8
9
|
const createError = errorsModule.createError
|
|
9
10
|
const createEvent = errorsModule.createEvent
|
|
@@ -129,7 +130,7 @@ class ErrorCollector {
|
|
|
129
130
|
if (transaction.userErrors.length) {
|
|
130
131
|
for (let i = 0; i < transaction.userErrors.length; i++) {
|
|
131
132
|
const exception = transaction.userErrors[i]
|
|
132
|
-
if (this.
|
|
133
|
+
if (this.collect(transaction, exception)) {
|
|
133
134
|
++collectedErrors
|
|
134
135
|
}
|
|
135
136
|
}
|
|
@@ -145,13 +146,13 @@ class ErrorCollector {
|
|
|
145
146
|
if (transaction.exceptions.length) {
|
|
146
147
|
for (let i = 0; i < transaction.exceptions.length; i++) {
|
|
147
148
|
const exception = transaction.exceptions[i]
|
|
148
|
-
if (this.collect(transaction, exception
|
|
149
|
+
if (this.collect(transaction, exception)) {
|
|
149
150
|
++collectedErrors
|
|
150
151
|
// if we could collect it, then check if expected
|
|
151
152
|
if (isExpectedErrorStatusCode ||
|
|
152
153
|
errorHelper.isExpectedException(
|
|
153
154
|
transaction,
|
|
154
|
-
exception
|
|
155
|
+
exception.error,
|
|
155
156
|
this.config,
|
|
156
157
|
urltils
|
|
157
158
|
)
|
|
@@ -178,31 +179,32 @@ class ErrorCollector {
|
|
|
178
179
|
}
|
|
179
180
|
|
|
180
181
|
/**
|
|
181
|
-
* This function collects the error right away when transaction is not supplied.
|
|
182
|
-
*
|
|
182
|
+
* This function collects the error right away when transaction is not supplied. Otherwise it
|
|
183
|
+
* delays collecting the error until the transaction ends.
|
|
183
184
|
*
|
|
184
185
|
* NOTE: this interface is unofficial and may change in future.
|
|
185
186
|
*
|
|
186
|
-
* @param {?Transaction}
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* @param {Error} exception
|
|
190
|
-
* The error to be traced.
|
|
191
|
-
*
|
|
192
|
-
* @param {object} customAttributes
|
|
193
|
-
* Any custom attributes associated with the request (optional).
|
|
187
|
+
* @param {?Transaction} transaction Transaction associated with the error.
|
|
188
|
+
* @param {Error} error The error to be traced.
|
|
189
|
+
* @param {?object} customAttributes Custom attributes associated with the request (optional).
|
|
194
190
|
*/
|
|
195
|
-
add(transaction,
|
|
196
|
-
if (!
|
|
191
|
+
add(transaction, error, customAttributes) {
|
|
192
|
+
if (!error) {
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (errorHelper.shouldIgnoreError(transaction, error, this.config)) {
|
|
197
|
+
logger.trace('Ignoring error')
|
|
197
198
|
return
|
|
198
199
|
}
|
|
199
200
|
|
|
200
201
|
const timestamp = Date.now()
|
|
202
|
+
const exception = new Exception({error, timestamp, customAttributes})
|
|
201
203
|
|
|
202
204
|
if (transaction) {
|
|
203
|
-
transaction.addException(exception
|
|
205
|
+
transaction.addException(exception)
|
|
204
206
|
} else {
|
|
205
|
-
this.collect(transaction, exception
|
|
207
|
+
this.collect(transaction, exception)
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
|
|
@@ -217,95 +219,54 @@ class ErrorCollector {
|
|
|
217
219
|
*
|
|
218
220
|
* NOTE: this interface is unofficial and may change in future.
|
|
219
221
|
*
|
|
220
|
-
* @param {?Transaction}
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* @param {Error} exception
|
|
224
|
-
* The error to be traced.
|
|
225
|
-
*
|
|
226
|
-
* @param {object} [customAttributes=null]
|
|
227
|
-
* Any custom attributes associated with the request (optional).
|
|
222
|
+
* @param {?Transaction} transaction Transaction associated with the error.
|
|
223
|
+
* @param {Exception} exception The Exception to be traced.
|
|
228
224
|
*/
|
|
229
|
-
addUserError(transaction,
|
|
230
|
-
if (!
|
|
225
|
+
addUserError(transaction, error, customAttributes) {
|
|
226
|
+
if (!error) return
|
|
231
227
|
|
|
232
|
-
|
|
228
|
+
const timestamp = Date.now()
|
|
229
|
+
const exception = new Exception({error, timestamp, customAttributes})
|
|
233
230
|
|
|
234
231
|
if (transaction) {
|
|
235
|
-
transaction.addUserError(exception
|
|
232
|
+
transaction.addUserError(exception)
|
|
236
233
|
} else {
|
|
237
|
-
this.
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Wrapper for _collect, include logic for whether an error should
|
|
243
|
-
* be ignored or not. Exists to allow userErrors to bypass ignore
|
|
244
|
-
* logic.
|
|
245
|
-
*
|
|
246
|
-
* NOTE: this interface is unofficial and may change in future.
|
|
247
|
-
*
|
|
248
|
-
* @param {?Transaction} transaction
|
|
249
|
-
* Transaction associated with the error.
|
|
250
|
-
*
|
|
251
|
-
* @param {?Error} exception
|
|
252
|
-
* The error to be traced.
|
|
253
|
-
*
|
|
254
|
-
* @param {?object} customAttributes
|
|
255
|
-
* Any custom attributes associated with the request.
|
|
256
|
-
*
|
|
257
|
-
* @param {number} timestamp
|
|
258
|
-
*
|
|
259
|
-
* @return {bool} True if the error was collected.
|
|
260
|
-
*/
|
|
261
|
-
collect(transaction, exception, customAttributes, timestamp) {
|
|
262
|
-
if (errorHelper.shouldIgnoreError(transaction, exception, this.config)) {
|
|
263
|
-
logger.trace("Ignoring error")
|
|
264
|
-
return
|
|
234
|
+
this.collect(transaction, exception)
|
|
265
235
|
}
|
|
266
|
-
return this._collect(transaction, exception, customAttributes, timestamp)
|
|
267
236
|
}
|
|
268
237
|
|
|
269
238
|
/**
|
|
270
239
|
* Collects the error and also creates the error event.
|
|
271
240
|
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
* This function uses an array of seen exceptions to ensure errors don't get
|
|
275
|
-
* double-counted. It can also be used as an unofficial means of marking that
|
|
276
|
-
* user errors shouldn't be traced.
|
|
241
|
+
* This function uses an array of seen exceptions to ensure errors don't get double-counted. It
|
|
242
|
+
* can also be used as an unofficial means of marking that user errors shouldn't be traced.
|
|
277
243
|
*
|
|
278
|
-
* For an error to be traced, at least one of the transaction or the error
|
|
279
|
-
* must be present.
|
|
244
|
+
* For an error to be traced, at least one of the transaction or the error must be present.
|
|
280
245
|
*
|
|
281
246
|
* NOTE: this interface is unofficial and may change in future.
|
|
282
247
|
*
|
|
283
|
-
* @param
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* @param {?Error} exception
|
|
287
|
-
* The error to be traced.
|
|
288
|
-
*
|
|
289
|
-
* @param {?object} customAttributes
|
|
290
|
-
* Any custom attributes associated with the request.
|
|
291
|
-
*
|
|
292
|
-
* @param {number} timestamp
|
|
293
|
-
*
|
|
294
|
-
* @return {bool} True if the error was collected.
|
|
248
|
+
* @param {?Transaction} transaction Transaction associated with the error.
|
|
249
|
+
* @param {?Exception} exception The Exception object to be traced.
|
|
250
|
+
* @return {bool} True if the error was collected.
|
|
295
251
|
*/
|
|
296
|
-
|
|
297
|
-
if (exception) {
|
|
298
|
-
|
|
252
|
+
collect(transaction, exception) {
|
|
253
|
+
if (!exception) {
|
|
254
|
+
exception = new Exception({})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (exception.error) {
|
|
258
|
+
if (this._haveSeen(transaction, exception.error)) {
|
|
299
259
|
return false
|
|
300
260
|
}
|
|
301
261
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
262
|
+
const error = exception.error
|
|
263
|
+
if (typeof error !== 'string' && !error.message && !error.stack) {
|
|
264
|
+
logger.trace(error, 'Got error that is not an instance of Error or string.')
|
|
265
|
+
exception.error = null
|
|
305
266
|
}
|
|
306
267
|
}
|
|
307
268
|
|
|
308
|
-
if (!exception && (!transaction || !transaction.statusCode || transaction.error)) {
|
|
269
|
+
if (!exception.error && (!transaction || !transaction.statusCode || transaction.error)) {
|
|
309
270
|
return false
|
|
310
271
|
}
|
|
311
272
|
|
|
@@ -321,13 +282,13 @@ class ErrorCollector {
|
|
|
321
282
|
return false
|
|
322
283
|
}
|
|
323
284
|
|
|
324
|
-
if (exception) {
|
|
325
|
-
logger.trace(exception, 'Got exception to trace:')
|
|
285
|
+
if (exception.error) {
|
|
286
|
+
logger.trace(exception.error, 'Got exception to trace:')
|
|
326
287
|
}
|
|
327
288
|
|
|
328
|
-
const
|
|
289
|
+
const errorTrace = createError(transaction, exception, this.config)
|
|
329
290
|
|
|
330
|
-
const isExpectedError = true ===
|
|
291
|
+
const isExpectedError = true === errorTrace[4].intrinsics['error.expected']
|
|
331
292
|
|
|
332
293
|
if (isExpectedError) {
|
|
333
294
|
this.metrics.getOrCreateMetric(NAMES.ERRORS.EXPECTED).incrementCallCount()
|
|
@@ -343,11 +304,11 @@ class ErrorCollector {
|
|
|
343
304
|
}
|
|
344
305
|
}
|
|
345
306
|
|
|
346
|
-
this.traceAggregator.add(
|
|
307
|
+
this.traceAggregator.add(errorTrace)
|
|
347
308
|
|
|
348
309
|
if (this.config.error_collector.capture_events === true) {
|
|
349
310
|
const priority = transaction && transaction.priority || Math.random()
|
|
350
|
-
const event = createEvent(transaction,
|
|
311
|
+
const event = createEvent(transaction, errorTrace, exception.timestamp, this.config)
|
|
351
312
|
this.eventAggregator.add(event, priority)
|
|
352
313
|
}
|
|
353
314
|
|
package/lib/errors/helper.js
CHANGED
|
@@ -48,7 +48,7 @@ module.exports = {
|
|
|
48
48
|
|
|
49
49
|
extractErrorInformation: function extractErrorInformation(
|
|
50
50
|
transaction,
|
|
51
|
-
|
|
51
|
+
error,
|
|
52
52
|
config,
|
|
53
53
|
urltils
|
|
54
54
|
) {
|
|
@@ -58,21 +58,21 @@ module.exports = {
|
|
|
58
58
|
|
|
59
59
|
// String errors do not provide us with as much information to provide to the
|
|
60
60
|
// user, but it is a common pattern.
|
|
61
|
-
if (typeof
|
|
62
|
-
message =
|
|
61
|
+
if (typeof error === 'string') {
|
|
62
|
+
message = error
|
|
63
63
|
} else if (
|
|
64
|
-
|
|
65
|
-
typeof
|
|
66
|
-
|
|
64
|
+
error !== null &&
|
|
65
|
+
typeof error === 'object' &&
|
|
66
|
+
error.message &&
|
|
67
67
|
!config.high_security &&
|
|
68
68
|
!config.strip_exception_messages.enabled
|
|
69
69
|
) {
|
|
70
|
-
message =
|
|
70
|
+
message = error.message
|
|
71
71
|
|
|
72
|
-
if (
|
|
73
|
-
type =
|
|
74
|
-
} else if (
|
|
75
|
-
type =
|
|
72
|
+
if (error.name) {
|
|
73
|
+
type = error.name
|
|
74
|
+
} else if (error.constructor && error.constructor.name) {
|
|
75
|
+
type = error.constructor.name
|
|
76
76
|
}
|
|
77
77
|
} else if (transaction && transaction.statusCode &&
|
|
78
78
|
urltils.isError(config, transaction.statusCode)) {
|
|
@@ -95,9 +95,9 @@ module.exports = {
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
|
|
98
|
-
shouldIgnoreError: function shouldIgnoreError(transaction,
|
|
98
|
+
shouldIgnoreError: function shouldIgnoreError(transaction, error, config) {
|
|
99
99
|
// extract _just_ the error information, not transaction stuff
|
|
100
|
-
let errorInfo = this.extractErrorInformation(null,
|
|
100
|
+
let errorInfo = this.extractErrorInformation(null, error, config, null)
|
|
101
101
|
|
|
102
102
|
return this.shouldIgnoreErrorClass(errorInfo, config) ||
|
|
103
103
|
this.shouldIgnoreErrorMessage(errorInfo, config) ||
|
package/lib/errors/index.js
CHANGED
|
@@ -6,8 +6,18 @@ var props = require('../util/properties')
|
|
|
6
6
|
var urltils = require('../util/urltils')
|
|
7
7
|
const errorHelper = require('../errors/helper')
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
class Exception {
|
|
10
|
+
constructor({error, timestamp, customAttributes, agentAttributes}) {
|
|
11
|
+
this.error = error
|
|
12
|
+
this.timestamp = timestamp || 0
|
|
13
|
+
this.customAttributes = customAttributes || {}
|
|
14
|
+
this.agentAttributes = agentAttributes || {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getErrorDetails(config) {
|
|
18
|
+
return errorHelper.extractErrorInformation(null, this.error, config)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
/**
|
|
13
23
|
* Given either or both of a transaction and an exception, generate an error
|
|
@@ -17,21 +27,20 @@ module.exports.createEvent = createEvent
|
|
|
17
27
|
* handler, which traps actual instances of Error, try to set sensible
|
|
18
28
|
* defaults for everything.
|
|
19
29
|
*
|
|
20
|
-
* @param {Transaction} transaction
|
|
21
|
-
*
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {object} customAttributes Any custom attributes associated with
|
|
24
|
-
* the request (optional).
|
|
30
|
+
* @param {Transaction} transaction The agent transaction, coming from the instrumentatation
|
|
31
|
+
* @param {Exception} exception An custom Exception object with the error and other information
|
|
32
|
+
* @param {object} config The configuration to use when creating the object
|
|
25
33
|
*/
|
|
26
|
-
function createError(transaction, exception,
|
|
34
|
+
function createError(transaction, exception, config) {
|
|
35
|
+
const error = exception.error
|
|
27
36
|
let {name, message, type} = errorHelper.extractErrorInformation(
|
|
28
37
|
transaction,
|
|
29
|
-
|
|
38
|
+
error,
|
|
30
39
|
config,
|
|
31
40
|
urltils
|
|
32
41
|
)
|
|
33
42
|
|
|
34
|
-
|
|
43
|
+
let params = {
|
|
35
44
|
userAttributes: Object.create(null),
|
|
36
45
|
agentAttributes: Object.create(null),
|
|
37
46
|
intrinsics: Object.create(null)
|
|
@@ -39,20 +48,26 @@ function createError(transaction, exception, customAttributes, config) {
|
|
|
39
48
|
|
|
40
49
|
if (transaction) {
|
|
41
50
|
// Copy all of the parameters off of the transaction.
|
|
42
|
-
params.agentAttributes = transaction.trace.attributes.get(DESTINATIONS.ERROR_EVENT)
|
|
43
51
|
params.intrinsics = transaction.getIntrinsicAttributes()
|
|
52
|
+
let transactionAgentAttributes = transaction.trace.attributes.get(DESTINATIONS.ERROR_EVENT)
|
|
53
|
+
transactionAgentAttributes = transactionAgentAttributes || {}
|
|
54
|
+
|
|
55
|
+
// Merge the agent attributes specific to this error event with the transaction attributes
|
|
56
|
+
const agentAttributes = Object.assign(exception.agentAttributes, transactionAgentAttributes)
|
|
57
|
+
params.agentAttributes = agentAttributes
|
|
44
58
|
|
|
45
59
|
// There should be no attributes to copy in HSM, but check status anyway
|
|
46
60
|
if (!config.high_security) {
|
|
47
|
-
|
|
61
|
+
const custom = transaction.trace.custom.get(DESTINATIONS.ERROR_EVENT)
|
|
48
62
|
urltils.overwriteParameters(custom, params.userAttributes)
|
|
49
63
|
}
|
|
50
64
|
}
|
|
51
65
|
|
|
66
|
+
const customAttributes = exception.customAttributes
|
|
52
67
|
if (!config.high_security && config.api.custom_attributes_enabled && customAttributes) {
|
|
53
|
-
for (
|
|
68
|
+
for (let key in customAttributes) {
|
|
54
69
|
if (props.hasOwn(customAttributes, key)) {
|
|
55
|
-
|
|
70
|
+
const dest = config.attributeFilter.filterTransaction(
|
|
56
71
|
DESTINATIONS.ERROR_EVENT,
|
|
57
72
|
key
|
|
58
73
|
)
|
|
@@ -63,12 +78,11 @@ function createError(transaction, exception, customAttributes, config) {
|
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
|
|
66
|
-
|
|
67
|
-
var stack = exception && exception.stack
|
|
81
|
+
const stack = exception.error && exception.error.stack
|
|
68
82
|
if (stack) {
|
|
69
83
|
params.stack_trace = ('' + stack).split(/[\n\r]/g)
|
|
70
84
|
if (config.high_security || config.strip_exception_messages.enabled) {
|
|
71
|
-
params.stack_trace[0] = exception.name + ': <redacted>'
|
|
85
|
+
params.stack_trace[0] = exception.error.name + ': <redacted>'
|
|
72
86
|
}
|
|
73
87
|
}
|
|
74
88
|
|
|
@@ -77,7 +91,7 @@ function createError(transaction, exception, customAttributes, config) {
|
|
|
77
91
|
params.intrinsics['error.expected'] = true
|
|
78
92
|
}
|
|
79
93
|
|
|
80
|
-
|
|
94
|
+
let res = [0, name, message, type, params]
|
|
81
95
|
if (transaction) {
|
|
82
96
|
res.transaction = transaction.id
|
|
83
97
|
}
|
|
@@ -180,3 +194,7 @@ function _getErrorEventIntrinsicAttrs(
|
|
|
180
194
|
|
|
181
195
|
return attributes
|
|
182
196
|
}
|
|
197
|
+
|
|
198
|
+
module.exports.createError = createError
|
|
199
|
+
module.exports.createEvent = createEvent
|
|
200
|
+
module.exports.Exception = Exception
|
package/lib/feature_flags.js
CHANGED
|
@@ -6,8 +6,7 @@ exports.prerelease = {
|
|
|
6
6
|
await_support: true,
|
|
7
7
|
serverless_mode: true,
|
|
8
8
|
promise_segments: false,
|
|
9
|
-
reverse_naming_rules: false
|
|
10
|
-
dt_format_w3c: false
|
|
9
|
+
reverse_naming_rules: false
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
// flags that are no longer used for released features
|
|
@@ -20,7 +19,8 @@ exports.released = [
|
|
|
20
19
|
'native_metrics',
|
|
21
20
|
'protocol_17',
|
|
22
21
|
'send_request_uri_attribute',
|
|
23
|
-
'synthetics'
|
|
22
|
+
'synthetics',
|
|
23
|
+
'dt_format_w3c'
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
// flags that are no longer used for unreleased features
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const REQUEST_START_HEADER = 'x-request-start'
|
|
4
|
+
const QUEUE_HEADER = 'x-queue-start'
|
|
5
|
+
const CONTENT_LENGTH_REGEX = /^Content-Length$/i
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Extracts queue time from the incoming request headers.
|
|
9
|
+
*
|
|
10
|
+
* Queue time is provided by certain providers by stamping the request
|
|
11
|
+
* header with the time the request arrived at the router.
|
|
12
|
+
* @param {*} logger
|
|
13
|
+
* @param {*} requestHeaders
|
|
14
|
+
*/
|
|
15
|
+
function getQueueTime(logger, requestHeaders) {
|
|
16
|
+
const headerValue = requestHeaders[REQUEST_START_HEADER] || requestHeaders[QUEUE_HEADER]
|
|
17
|
+
if (!headerValue) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const split = headerValue.split('=')
|
|
22
|
+
const rawQueueTime = split.length > 1 ? split[1] : headerValue
|
|
23
|
+
|
|
24
|
+
const parsedQueueTime = parseFloat(rawQueueTime)
|
|
25
|
+
if (isNaN(parsedQueueTime)) {
|
|
26
|
+
logger.warn('Queue time header parsed as NaN. See trace level log for value.')
|
|
27
|
+
|
|
28
|
+
// This header can hold up to 4096 bytes which could quickly fill up logs.
|
|
29
|
+
// Do not log a level higher than debug.
|
|
30
|
+
logger.trace('Queue time: %s', rawQueueTime)
|
|
31
|
+
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const convertedQueueTime = convertUnit(parsedQueueTime)
|
|
36
|
+
return convertedQueueTime
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function convertUnit(time) {
|
|
40
|
+
let convertedTime = time
|
|
41
|
+
if (convertedTime > 1e18) {
|
|
42
|
+
// nano seconds
|
|
43
|
+
convertedTime = convertedTime / 1e6
|
|
44
|
+
} else if (convertedTime > 1e15) {
|
|
45
|
+
// micro seconds
|
|
46
|
+
convertedTime = convertedTime / 1e3
|
|
47
|
+
} else if (convertedTime < 1e12) {
|
|
48
|
+
// seconds
|
|
49
|
+
convertedTime = convertedTime * 1e3
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return convertedTime
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns the value of the Content-Length header
|
|
57
|
+
*
|
|
58
|
+
* If no header is found, returns -1
|
|
59
|
+
*
|
|
60
|
+
* @param {*} headers
|
|
61
|
+
*/
|
|
62
|
+
function getContentLengthFromHeaders(headers) {
|
|
63
|
+
let contentLength = -1
|
|
64
|
+
for (const [headerName, headerValue] of Object.entries(headers)) {
|
|
65
|
+
if (CONTENT_LENGTH_REGEX.test(headerName)) {
|
|
66
|
+
return headerValue
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return contentLength
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
getQueueTime,
|
|
74
|
+
getContentLengthFromHeaders
|
|
75
|
+
}
|
|
@@ -33,8 +33,20 @@ function initialize(agent, childProcess, moduleName, shim) {
|
|
|
33
33
|
const args = shim.argsToArray.apply(shim, arguments)
|
|
34
34
|
const cbIndex = args.length - 1
|
|
35
35
|
|
|
36
|
+
const originalListener = args[cbIndex]
|
|
37
|
+
if (!shim.isFunction(originalListener)) {
|
|
38
|
+
return fn.apply(this, arguments)
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
shim.bindSegment(args, cbIndex)
|
|
37
42
|
|
|
43
|
+
// Leverage events.removeListener() mechanism that checks listener
|
|
44
|
+
// property to allow our wrapped listeners to match and remove appropriately.
|
|
45
|
+
// Avoids having to instrument removeListener() and potentially doubling
|
|
46
|
+
// lookup. Since our wrapping will only be referenced by the events
|
|
47
|
+
// collection, we should not need to unwrap.
|
|
48
|
+
args[cbIndex].listener = originalListener
|
|
49
|
+
|
|
38
50
|
return fn.apply(this, args)
|
|
39
51
|
}
|
|
40
52
|
}
|
|
@@ -17,7 +17,6 @@ const DEFAULT_PORT = 80
|
|
|
17
17
|
const DEFAULT_SSL_PORT = 443
|
|
18
18
|
|
|
19
19
|
const NEWRELIC_ID_HEADER = 'x-newrelic-id'
|
|
20
|
-
const NEWRELIC_TRACE_HEADER = 'newrelic'
|
|
21
20
|
const NEWRELIC_TRANSACTION_HEADER = 'x-newrelic-transaction'
|
|
22
21
|
const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
|
|
23
22
|
|
|
@@ -92,11 +91,9 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
|
|
|
92
91
|
// TODO: abstract header logic shared with TransactionShim#insertCATRequestHeaders
|
|
93
92
|
if (agent.config.distributed_tracing.enabled) {
|
|
94
93
|
if (opts.headers && opts.headers[SHIM_SYMBOLS.DISABLE_DT]) {
|
|
95
|
-
logger.trace('
|
|
96
|
-
} else if (agent.config.feature_flag.dt_format_w3c) {
|
|
97
|
-
_addTraceContextHeaders(transaction, outboundHeaders)
|
|
94
|
+
logger.trace('Distributed tracing disabled by instrumentation.')
|
|
98
95
|
} else {
|
|
99
|
-
|
|
96
|
+
transaction.insertDistributedTraceHeaders(outboundHeaders)
|
|
100
97
|
}
|
|
101
98
|
} else if (agent.config.cross_application_tracer.enabled) {
|
|
102
99
|
if (agent.config.encoding_key) {
|
|
@@ -198,6 +195,10 @@ function handleError(segment, req, error) {
|
|
|
198
195
|
* @param {http.IncomingMessage} res
|
|
199
196
|
*/
|
|
200
197
|
function handleResponse(segment, hostname, req, res) {
|
|
198
|
+
// Add response attributes for spans
|
|
199
|
+
segment.addAttribute('http.statusCode', res.statusCode)
|
|
200
|
+
segment.addAttribute('http.statusText', res.statusMessage)
|
|
201
|
+
|
|
201
202
|
// If CAT is enabled, grab those headers!
|
|
202
203
|
const agent = segment.transaction.agent
|
|
203
204
|
if (
|
|
@@ -276,29 +277,6 @@ function _makeNonEnumerable(obj, prop) {
|
|
|
276
277
|
}
|
|
277
278
|
}
|
|
278
279
|
|
|
279
|
-
function _addDistributedHeaders(tx, outboundHeaders) {
|
|
280
|
-
try {
|
|
281
|
-
const txData = tx.createDistributedTracePayload().httpSafe()
|
|
282
|
-
outboundHeaders[NEWRELIC_TRACE_HEADER] = txData
|
|
283
|
-
|
|
284
|
-
logger.trace(
|
|
285
|
-
'Added outbound request distributed tracing headers in transaction %s',
|
|
286
|
-
tx.id
|
|
287
|
-
)
|
|
288
|
-
} catch (err) {
|
|
289
|
-
logger.trace(err, 'Failed to create distributed trace payload')
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function _addTraceContextHeaders(tx, outboundHeaders) {
|
|
294
|
-
tx.traceContext.addTraceContextHeaders(outboundHeaders)
|
|
295
|
-
|
|
296
|
-
logger.trace(
|
|
297
|
-
'Added outbound request w3c trace context headers in transaction %s',
|
|
298
|
-
tx.id
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
|
|
302
280
|
function _addCATHeaders(agent, tx, outboundHeaders) {
|
|
303
281
|
if (agent.config.obfuscatedId) {
|
|
304
282
|
outboundHeaders[NEWRELIC_ID_HEADER] = agent.config.obfuscatedId
|