newrelic 9.4.0 → 9.6.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/NEWS.md +18 -0
- package/README.md +8 -6
- package/index.js +6 -5
- package/lib/collector/remote-method.js +2 -1
- package/lib/config/default.js +528 -287
- package/lib/config/formatters.js +108 -0
- package/lib/config/index.js +69 -91
- package/lib/instrumentation/@hapi/hapi.js +229 -1
- package/lib/instrumentation/{vision.js → @hapi/vision.js} +0 -0
- package/lib/instrumentation/core/async_hooks.js +1 -4
- package/lib/instrumentation/core/globals.js +2 -3
- package/lib/instrumentation/core/http-outbound.js +3 -5
- package/lib/instrumentation/core/http.js +6 -19
- package/lib/instrumentation/core/timers.js +3 -1
- package/lib/instrumentation/mysql/mysql.js +6 -5
- package/lib/instrumentation/promise.js +16 -15
- package/lib/instrumentation/undici.js +10 -15
- package/lib/instrumentations.js +1 -1
- package/lib/shim/constants.js +1 -16
- package/lib/shim/datastore-shim.js +2 -1
- package/lib/shim/promise-shim.js +18 -17
- package/lib/shim/shim.js +37 -82
- package/lib/shim/transaction-shim.js +1 -1
- package/lib/shim/webframework-shim.js +2 -8
- package/lib/shimmer.js +29 -23
- package/lib/symbols.js +26 -0
- package/lib/system-info.js +1 -2
- package/lib/transaction/tracer/index.js +12 -18
- package/lib/util/arity.js +4 -9
- package/lib/util/properties.js +0 -46
- package/package.json +3 -3
- package/lib/config/env.js +0 -294
- package/lib/instrumentation/hapi/hapi.js +0 -207
- package/lib/instrumentation/hapi/shared.js +0 -28
- package/lib/instrumentation/hapi.js +0 -254
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const formatters = module.exports
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Splits a string by a ',' and trims whitespace
|
|
11
|
+
*
|
|
12
|
+
* @param {string} val config setting
|
|
13
|
+
* @param {Array}
|
|
14
|
+
*/
|
|
15
|
+
formatters.array = function array(val) {
|
|
16
|
+
return val.split(',').map((k) => k.trim())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parses a config setting as an int
|
|
21
|
+
*
|
|
22
|
+
* @param {string} val config setting
|
|
23
|
+
* @returns {int}
|
|
24
|
+
*/
|
|
25
|
+
formatters.int = function int(val) {
|
|
26
|
+
return parseInt(val, 10)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Parses a config setting as a float
|
|
31
|
+
*
|
|
32
|
+
* @param {string} val config setting
|
|
33
|
+
* @returns {float}
|
|
34
|
+
*/
|
|
35
|
+
formatters.float = function float(val) {
|
|
36
|
+
return parseFloat(val, 10)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parses a config setting as a boolean
|
|
41
|
+
*
|
|
42
|
+
* @param {string} val config setting
|
|
43
|
+
* @param setting
|
|
44
|
+
* @returns {boolean}
|
|
45
|
+
*/
|
|
46
|
+
formatters.boolean = function boolean(setting) {
|
|
47
|
+
if (setting == null) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const normalized = setting.toString().toLowerCase()
|
|
52
|
+
switch (normalized) {
|
|
53
|
+
case 'false':
|
|
54
|
+
case 'f':
|
|
55
|
+
case 'no':
|
|
56
|
+
case 'n':
|
|
57
|
+
case 'disabled':
|
|
58
|
+
case '0':
|
|
59
|
+
return false
|
|
60
|
+
|
|
61
|
+
default:
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Parses a config setting as an object
|
|
68
|
+
*
|
|
69
|
+
* @param {string} val config setting
|
|
70
|
+
* @param {logger} logger agent logger instance
|
|
71
|
+
* @returns {object}
|
|
72
|
+
*/
|
|
73
|
+
formatters.object = function object(val, logger) {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(val)
|
|
76
|
+
} catch (error) {
|
|
77
|
+
logger.error('New Relic configurator could not deserialize object:')
|
|
78
|
+
logger.error(error.stack)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Parse a config setting as a collection with 1 object
|
|
84
|
+
*
|
|
85
|
+
* @param {string} val config setting
|
|
86
|
+
* @param {logger} logger agent logger instance
|
|
87
|
+
* @returns {Array}
|
|
88
|
+
*/
|
|
89
|
+
formatters.objectList = function objectList(val, logger) {
|
|
90
|
+
try {
|
|
91
|
+
return JSON.parse('[' + val + ']')
|
|
92
|
+
} catch (error) {
|
|
93
|
+
logger.error('New Relic configurator could not deserialize object list:')
|
|
94
|
+
logger.error(error.stack)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Checks if a value is within an allow list. If not it assigns
|
|
100
|
+
* the first element in allow list as default
|
|
101
|
+
*
|
|
102
|
+
* @param {Array} list allowable values
|
|
103
|
+
* @param {string} val config setting
|
|
104
|
+
* @returns {string}
|
|
105
|
+
*/
|
|
106
|
+
formatters.allowList = function allowList(list, val) {
|
|
107
|
+
return list.includes(val) ? val : list[0]
|
|
108
|
+
}
|
package/lib/config/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
const AttributeFilter = require('./attribute-filter')
|
|
9
9
|
const CollectorResponse = require('../collector/response')
|
|
10
10
|
const copy = require('../util/copy')
|
|
11
|
-
const defaultConfig = require('./default')
|
|
11
|
+
const { config: defaultConfig, definition, setNestedKey } = require('./default')
|
|
12
12
|
const EventEmitter = require('events').EventEmitter
|
|
13
13
|
const featureFlag = require('../feature_flags')
|
|
14
14
|
const flatten = require('../util/flatten')
|
|
@@ -22,6 +22,8 @@ const util = require('util')
|
|
|
22
22
|
const MergeServerConfig = require('./merge-server-config')
|
|
23
23
|
const harvestConfigValidator = require('./harvest-config-validator')
|
|
24
24
|
const mergeServerConfig = new MergeServerConfig()
|
|
25
|
+
const { boolean: isTruthular } = require('./formatters')
|
|
26
|
+
const configDefinition = definition()
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* CONSTANTS -- we gotta lotta 'em
|
|
@@ -33,11 +35,10 @@ const BASE_CONFIG_PATH = require.resolve('../../newrelic')
|
|
|
33
35
|
const HAS_ARBITRARY_KEYS = new Set(['ignore_messages', 'expected_messages', 'labels'])
|
|
34
36
|
|
|
35
37
|
const LASP_MAP = require('./lasp').LASP_MAP
|
|
36
|
-
const ENV = require('./env')
|
|
37
38
|
const HSM = require('./hsm')
|
|
38
39
|
const REMOVE_BEFORE_SEND = new Set(['attributeFilter'])
|
|
39
40
|
|
|
40
|
-
const exists = fs.existsSync
|
|
41
|
+
const exists = fs.existsSync
|
|
41
42
|
let logger = null // Lazy-loaded in `initialize`.
|
|
42
43
|
let _configInstance = null
|
|
43
44
|
|
|
@@ -56,35 +57,6 @@ const getConfigFileLocations = () =>
|
|
|
56
57
|
: undefined
|
|
57
58
|
].filter(Boolean)
|
|
58
59
|
|
|
59
|
-
function isTruthular(setting) {
|
|
60
|
-
if (setting == null) {
|
|
61
|
-
return false
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const normalized = setting.toString().toLowerCase()
|
|
65
|
-
switch (normalized) {
|
|
66
|
-
case 'false':
|
|
67
|
-
case 'f':
|
|
68
|
-
case 'no':
|
|
69
|
-
case 'n':
|
|
70
|
-
case 'disabled':
|
|
71
|
-
case '0':
|
|
72
|
-
return false
|
|
73
|
-
|
|
74
|
-
default:
|
|
75
|
-
return true
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function fromObjectList(setting) {
|
|
80
|
-
try {
|
|
81
|
-
return JSON.parse('[' + setting + ']')
|
|
82
|
-
} catch (error) {
|
|
83
|
-
logger.error('New Relic configurator could not deserialize object list:')
|
|
84
|
-
logger.error(error.stack)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
60
|
function _findConfigFile() {
|
|
89
61
|
const configFileCandidates = getConfigFileLocations().reduce((files, configPath) => {
|
|
90
62
|
const configFiles = getConfigFileNames().map((filename) =>
|
|
@@ -145,11 +117,6 @@ function Config(config) {
|
|
|
145
117
|
this.collect_errors = true
|
|
146
118
|
this.collect_span_events = true
|
|
147
119
|
|
|
148
|
-
// override options for utilization stats
|
|
149
|
-
this.utilization.logical_processors = null
|
|
150
|
-
this.utilization.total_ram_mib = null
|
|
151
|
-
this.utilization.billing_hostname = null
|
|
152
|
-
|
|
153
120
|
this.browser_monitoring.loader = 'rum'
|
|
154
121
|
this.browser_monitoring.loader_version = ''
|
|
155
122
|
|
|
@@ -1057,66 +1024,77 @@ Config.prototype._featureFlagsFromEnv = function _featureFlagsFromEnv() {
|
|
|
1057
1024
|
}
|
|
1058
1025
|
|
|
1059
1026
|
/**
|
|
1060
|
-
*
|
|
1061
|
-
* environment variable names, overriding any configuration values that are
|
|
1062
|
-
* found in the environment. Operates purely via side effects.
|
|
1027
|
+
* Creates an env var mapper from the configuration path value
|
|
1063
1028
|
*
|
|
1064
|
-
* @param
|
|
1065
|
-
*
|
|
1066
|
-
* @
|
|
1067
|
-
* never need to set this yourself.
|
|
1068
|
-
* @param metadata
|
|
1069
|
-
* @param data
|
|
1029
|
+
* @param {string} key of configuration value
|
|
1030
|
+
* @param {Array} paths list of leaf nodes leading to configuration value
|
|
1031
|
+
* @returns {string} formatted env var name
|
|
1070
1032
|
*/
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
}
|
|
1033
|
+
function deriveEnvVar(key, paths) {
|
|
1034
|
+
let path = paths.join('_')
|
|
1035
|
+
path = path ? `${path}_` : path
|
|
1036
|
+
const envKey = `NEW_RELIC_${path.toUpperCase()}${key.toUpperCase()}`
|
|
1037
|
+
return envKey
|
|
1038
|
+
}
|
|
1078
1039
|
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1040
|
+
/**
|
|
1041
|
+
* Assigns the value of an env var to its corresponding configuration path
|
|
1042
|
+
*
|
|
1043
|
+
* @param {object} params
|
|
1044
|
+
* @param {object} params.config agent config
|
|
1045
|
+
* @param {string} params.key key to assign value
|
|
1046
|
+
* @param {string} params.envVar name of env var
|
|
1047
|
+
* @param {Function} params.formatter function to coerce env var as they are all strings
|
|
1048
|
+
* @param {Array} params.paths list of leaf nodes leading to the configuration value
|
|
1049
|
+
*/
|
|
1050
|
+
function setFromEnv({ config, key, envVar, formatter, paths }) {
|
|
1051
|
+
const setting = process.env[envVar]
|
|
1052
|
+
if (setting) {
|
|
1053
|
+
const formattedSetting = formatter ? formatter(setting, logger) : setting
|
|
1054
|
+
setNestedKey(config, [...paths, key], formattedSetting)
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1084
1057
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1058
|
+
/**
|
|
1059
|
+
* Recursively visit the nodes of the config definition and look for environment variable names, overriding any configuration values that are found.
|
|
1060
|
+
*
|
|
1061
|
+
* @param {object} [config=this] The current level of the configuration object.
|
|
1062
|
+
* @param {object} [data=configDefinition] The current level of the config definition object.
|
|
1063
|
+
* @param {Array} [paths=[]] keeps track of the nested path to properly derive the env var
|
|
1064
|
+
* @param {int} [objectKeys=1] indicator of how many keys exist in current node to know when to remove current node after all keys are processed
|
|
1065
|
+
*/
|
|
1066
|
+
Config.prototype._fromEnvironment = function _fromEnvironment(
|
|
1067
|
+
config = this,
|
|
1068
|
+
data = configDefinition,
|
|
1069
|
+
paths = [],
|
|
1070
|
+
objectKeys = 1
|
|
1071
|
+
) {
|
|
1072
|
+
let keysSeen = 0
|
|
1073
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
1074
|
+
const type = typeof value
|
|
1075
|
+
keysSeen++
|
|
1076
|
+
if (type === 'string') {
|
|
1077
|
+
const envVar = deriveEnvVar(key, paths)
|
|
1078
|
+
setFromEnv({ config, key, envVar, paths })
|
|
1079
|
+
} else if (type === 'object') {
|
|
1080
|
+
if (value.hasOwnProperty('env')) {
|
|
1081
|
+
setFromEnv({ config, key, envVar: value.env, paths, formatter: value.formatter })
|
|
1082
|
+
} else if (value.hasOwnProperty('default')) {
|
|
1083
|
+
const envVar = deriveEnvVar(key, paths)
|
|
1084
|
+
setFromEnv({ config, key, envVar, formatter: value.formatter, paths })
|
|
1085
|
+
} else {
|
|
1086
|
+
paths.push(key)
|
|
1087
|
+
const { length } = Object.keys(value)
|
|
1088
|
+
this._fromEnvironment(config, value, paths, length)
|
|
1116
1089
|
}
|
|
1117
|
-
this._fromEnvironment(node, data[value])
|
|
1118
1090
|
}
|
|
1119
|
-
}
|
|
1091
|
+
})
|
|
1092
|
+
|
|
1093
|
+
// we have traversed every key in current object leaf node, remove wrapping key
|
|
1094
|
+
// to properly derive env vars of future leaf nodes
|
|
1095
|
+
if (keysSeen === objectKeys) {
|
|
1096
|
+
paths.pop()
|
|
1097
|
+
}
|
|
1120
1098
|
}
|
|
1121
1099
|
|
|
1122
1100
|
/**
|
|
@@ -5,4 +5,232 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const record = require('../../metrics/recorders/generic')
|
|
9
|
+
// This object defines all the events that we want to wrap extensions
|
|
10
|
+
// for, as they are the only ones associated with requests.
|
|
11
|
+
const ROUTE_EVENTS = {
|
|
12
|
+
onRequest: true,
|
|
13
|
+
onPreAuth: true,
|
|
14
|
+
onCredentials: true,
|
|
15
|
+
onPostAuth: true,
|
|
16
|
+
onPreHandler: true,
|
|
17
|
+
onPostHandler: true,
|
|
18
|
+
onPreResponse: true,
|
|
19
|
+
|
|
20
|
+
// Server events
|
|
21
|
+
onPreStart: false,
|
|
22
|
+
onPostStart: false,
|
|
23
|
+
onPreStop: false,
|
|
24
|
+
onPostStop: false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = function initialize(agent, hapi, moduleName, shim) {
|
|
28
|
+
if (!agent || !hapi || !shim) {
|
|
29
|
+
shim &&
|
|
30
|
+
shim.logger.debug(
|
|
31
|
+
'Hapi instrumentation function called with incorrect arguments, not instrumenting.'
|
|
32
|
+
)
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
shim.setFramework(shim.HAPI)
|
|
37
|
+
|
|
38
|
+
shim.setErrorPredicate(function hapiErrorPredicate(err) {
|
|
39
|
+
return err instanceof Error
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// At this point, framework and error predicate have both already been set via ./hapi,
|
|
43
|
+
// so we only need to set the response predicate and wrap the server object
|
|
44
|
+
shim.setResponsePredicate(function hapiResponsePredicate(args, result) {
|
|
45
|
+
return !(result instanceof Error) && result !== args[1].continue
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// 'Server' and 'server' both point to the same export,
|
|
49
|
+
// but we can't make any assumption about which will be used.
|
|
50
|
+
// Since we wrap the prototype, the second wrap should exit early.
|
|
51
|
+
shim.wrapReturn(hapi, 'server', serverFactoryWrapper)
|
|
52
|
+
shim.wrapReturn(hapi, 'Server', serverFactoryWrapper)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function serverFactoryWrapper(shim, fn, fnName, server) {
|
|
56
|
+
serverPostConstructor.call(server, shim)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function serverPostConstructor(shim) {
|
|
60
|
+
const proto = Object.getPrototypeOf(this)
|
|
61
|
+
|
|
62
|
+
if (shim.isWrapped(proto.decorate)) {
|
|
63
|
+
shim.logger.trace('Already wrapped Server proto, not wrapping again')
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
shim.wrap(proto, 'decorate', function wrapDecorate(shim, original) {
|
|
68
|
+
return function wrappedDecorate(type) {
|
|
69
|
+
// server.decorate also accepts 'request', 'toolkit', 'server' types,
|
|
70
|
+
// but we're only concerned with 'handler'
|
|
71
|
+
if (type !== 'handler') {
|
|
72
|
+
return original.apply(this, arguments)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Convert arguments to usable array
|
|
76
|
+
const args = shim.argsToArray.apply(shim, arguments)
|
|
77
|
+
|
|
78
|
+
// Wrap the third server.decorate arg, the user-defined handler
|
|
79
|
+
shim.wrap(args, shim.THIRD, function wrapHandler(shim, fn) {
|
|
80
|
+
if (typeof fn !== 'function') {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (fn.defaults) {
|
|
85
|
+
wrappedHandler.defaults = fn.defaults
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return wrappedHandler
|
|
89
|
+
|
|
90
|
+
function wrappedHandler(route) {
|
|
91
|
+
const ret = fn.apply(this, arguments)
|
|
92
|
+
|
|
93
|
+
return typeof ret === 'function' ? wrapRouteHandler(shim, ret, route && route.path) : ret
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
return original.apply(this, args)
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
shim.wrap(proto, 'route', function wrapRoute(shim, original) {
|
|
102
|
+
return function wrappedRoute() {
|
|
103
|
+
const args = shim.argsToArray.apply(shim, arguments)
|
|
104
|
+
|
|
105
|
+
if (!shim.isObject(args[0])) {
|
|
106
|
+
return original.apply(this, args)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// If route is created via a plugin, pull prefix if it exists
|
|
110
|
+
const prefix =
|
|
111
|
+
(this.realm &&
|
|
112
|
+
this.realm.modifiers &&
|
|
113
|
+
this.realm.modifiers.route &&
|
|
114
|
+
this.realm.modifiers.route.prefix) ||
|
|
115
|
+
''
|
|
116
|
+
|
|
117
|
+
_wrapRoute(shim, args[0])
|
|
118
|
+
|
|
119
|
+
return original.apply(this, args)
|
|
120
|
+
|
|
121
|
+
function _wrapRoute(shim, route) {
|
|
122
|
+
const routePath = prefix + route.path
|
|
123
|
+
if (shim.isArray(route)) {
|
|
124
|
+
for (let i = 0; i < route.length; ++i) {
|
|
125
|
+
_wrapRoute(shim, route[i])
|
|
126
|
+
}
|
|
127
|
+
return
|
|
128
|
+
} else if (route.options) {
|
|
129
|
+
// v17 now prefers `options` property...
|
|
130
|
+
if (route.options.pre) {
|
|
131
|
+
// config objects can also contain multiple OTHER handlers in a `pre` array
|
|
132
|
+
route.options.pre = wrapPreHandlers(shim, route.options.pre, routePath)
|
|
133
|
+
}
|
|
134
|
+
if (route.options.handler) {
|
|
135
|
+
_wrapRouteHandler(shim, route.options, routePath)
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
} else if (route.config) {
|
|
139
|
+
// ... but `config` still works
|
|
140
|
+
if (route.config.pre) {
|
|
141
|
+
route.config.pre = wrapPreHandlers(shim, route.config.pre, routePath)
|
|
142
|
+
}
|
|
143
|
+
if (route.config.handler) {
|
|
144
|
+
_wrapRouteHandler(shim, route.config, routePath)
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
_wrapRouteHandler(shim, route, routePath)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function _wrapRouteHandler(shim, container, path) {
|
|
152
|
+
if (typeof container.handler !== 'function') {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
shim.wrap(container, 'handler', function wrapHandler(shim, handler) {
|
|
156
|
+
return wrapRouteHandler(shim, handler, path)
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
shim.wrap(proto, 'ext', function wrapExt(shim, original) {
|
|
163
|
+
return function wrappedExt(event, method) {
|
|
164
|
+
const args = shim.argsToArray.apply(shim, arguments)
|
|
165
|
+
|
|
166
|
+
if (shim.isArray(event)) {
|
|
167
|
+
for (let i = 0; i < event.length; i++) {
|
|
168
|
+
event[i].method = wrapMiddleware(shim, event[i].method, event[i].type)
|
|
169
|
+
}
|
|
170
|
+
} else if (shim.isObject(event)) {
|
|
171
|
+
event.method = wrapMiddleware(shim, event.method, event.type)
|
|
172
|
+
} else if (shim.isString(event)) {
|
|
173
|
+
args[1] = wrapMiddleware(shim, method, event)
|
|
174
|
+
} else {
|
|
175
|
+
shim.logger.debug('Unsupported event type %j', event)
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return original.apply(this, args)
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function wrapPreHandlers(shim, container, path) {
|
|
185
|
+
if (shim.isArray(container)) {
|
|
186
|
+
for (let i = 0; i < container.length; ++i) {
|
|
187
|
+
container[i] = wrapPreHandlers(shim, container[i], path)
|
|
188
|
+
}
|
|
189
|
+
return container
|
|
190
|
+
} else if (shim.isFunction(container)) {
|
|
191
|
+
return wrapPreHandler(shim, container, path)
|
|
192
|
+
} else if (container.method && shim.isFunction(container.method)) {
|
|
193
|
+
return shim.wrap(container, 'method', function wrapHandler(shim, handler) {
|
|
194
|
+
return wrapPreHandler(shim, handler, path)
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function wrapPreHandler(shim, container, path) {
|
|
200
|
+
return shim.record(container, (shim) => {
|
|
201
|
+
return { name: [shim.HAPI, ' pre handler: ', '(', path, ')'].join(''), recorder: record }
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function wrapRouteHandler(shim, handler, path) {
|
|
206
|
+
return shim.recordMiddleware(handler, {
|
|
207
|
+
route: path,
|
|
208
|
+
req: function getReq(shim, fn, fnName, args) {
|
|
209
|
+
const request = args[0]
|
|
210
|
+
if (request && request.raw) {
|
|
211
|
+
return request.raw.req
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
promise: true,
|
|
215
|
+
params: function getParams(shim, fn, fnName, args) {
|
|
216
|
+
const req = args[0]
|
|
217
|
+
return req && req.params
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function wrapMiddleware(shim, middleware, event) {
|
|
223
|
+
if (!ROUTE_EVENTS[event]) {
|
|
224
|
+
return middleware
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return shim.recordMiddleware(middleware, {
|
|
228
|
+
route: event,
|
|
229
|
+
type: event === 'onPreResponse' ? shim.ERRORWARE : shim.MIDDLEWARE,
|
|
230
|
+
promise: true,
|
|
231
|
+
req: function getReq(shim, fn, fnName, args) {
|
|
232
|
+
const req = args[0]
|
|
233
|
+
return req && req.raw && req.raw.req
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
}
|
|
File without changes
|
|
@@ -38,7 +38,7 @@ function initialize(agent, shim) {
|
|
|
38
38
|
|
|
39
39
|
function getPromiseResolveStyleHooks(segmentMap, agent, shim) {
|
|
40
40
|
const hooks = {
|
|
41
|
-
init: function initHook(id, type, triggerId
|
|
41
|
+
init: function initHook(id, type, triggerId) {
|
|
42
42
|
if (type !== 'PROMISE') {
|
|
43
43
|
return
|
|
44
44
|
}
|
|
@@ -55,9 +55,6 @@ function getPromiseResolveStyleHooks(segmentMap, agent, shim) {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const activeSegment = shim.getActiveSegment() || parentSegment
|
|
58
|
-
if (asyncResource && asyncResource.promise) {
|
|
59
|
-
asyncResource.promise.__NR_id = id
|
|
60
|
-
}
|
|
61
58
|
|
|
62
59
|
segmentMap.set(id, activeSegment)
|
|
63
60
|
},
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const asyncHooks = require('./async_hooks')
|
|
9
|
+
const symbols = require('../../symbols')
|
|
9
10
|
|
|
10
11
|
module.exports = initialize
|
|
11
12
|
|
|
@@ -40,9 +41,7 @@ function initialize(agent, nodule, name, shim) {
|
|
|
40
41
|
if (ev === 'unhandledRejection' && error && !process.domain) {
|
|
41
42
|
if (process.listenerCount('unhandledRejection') === 0) {
|
|
42
43
|
// If there are no unhandledRejection handlers report the error.
|
|
43
|
-
const segment = promise.
|
|
44
|
-
? asyncHooks.segmentMap.get(promise.__NR_id)
|
|
45
|
-
: promise.__NR_context && promise.__NR_context.getSegment()
|
|
44
|
+
const segment = promise[symbols.context] && promise[symbols.context].getSegment()
|
|
46
45
|
const tx = segment && segment.transaction
|
|
47
46
|
shim.logger.trace('Captured unhandled rejection for transaction %s', tx && tx.id)
|
|
48
47
|
agent.errors.add(tx, error)
|
|
@@ -12,9 +12,9 @@ const logger = require('../../logger').child({ component: 'outbound' })
|
|
|
12
12
|
const shimmer = require('../../shimmer')
|
|
13
13
|
const url = require('url')
|
|
14
14
|
const copy = require('../../util/copy')
|
|
15
|
+
const symbols = require('../../symbols')
|
|
15
16
|
|
|
16
17
|
const NAMES = require('../../metrics/names')
|
|
17
|
-
const SHIM_SYMBOLS = require('../../shim/constants').SYMBOLS
|
|
18
18
|
|
|
19
19
|
const DEFAULT_HOST = 'localhost'
|
|
20
20
|
const DEFAULT_HTTP_PORT = 80
|
|
@@ -85,7 +85,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
|
|
|
85
85
|
|
|
86
86
|
// TODO: abstract header logic shared with TransactionShim#insertCATRequestHeaders
|
|
87
87
|
if (agent.config.distributed_tracing.enabled) {
|
|
88
|
-
if (opts.headers && opts.headers[
|
|
88
|
+
if (opts.headers && opts.headers[symbols.disableDT]) {
|
|
89
89
|
logger.trace('Distributed tracing disabled by instrumentation.')
|
|
90
90
|
} else {
|
|
91
91
|
transaction.insertDistributedTraceHeaders(outboundHeaders)
|
|
@@ -113,9 +113,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
|
|
|
113
113
|
const parsed = urltils.scrubAndParseParameters(request.path)
|
|
114
114
|
const proto = parsed.protocol || opts.protocol || 'http:'
|
|
115
115
|
segment.name += parsed.path
|
|
116
|
-
|
|
117
|
-
value: segment
|
|
118
|
-
})
|
|
116
|
+
request[symbols.segment] = segment
|
|
119
117
|
|
|
120
118
|
if (parsed.parameters) {
|
|
121
119
|
// Scrub and parse returns on object with a null prototype.
|